Index activity

Index changes.

Crates and versions added or updated, derived from the repository history for packages currently in the index.

158 manifest changes

69 new versions

89 development updates

  1. import validated gnat_flyology_native manifests

    0c8956fa on GitHub
  2. Publish validated tagged crate releases

    cbe19910 on GitHub
  3. Publish validated tagged crate releases

    48dafe34 on GitHub
  4. publish the flyology_crc 0.1.1 manifest

    7e008273 on GitHub
  5. publish the validated flyology_crc release

    8124bfd3 on GitHub
  6. Publish validated tagged crate releases

    122abd7e on GitHub
  7. add the flyology_cli development descriptor

    b287bf8f on GitHub
  8. Development updates

    Development update

    flyology_object_storage 0.1.0-dev

    10 updates: f28a3fb6 through 5eaf79cf

    S3 client and pluggable object-storage server for Flyology

    Manifest fields
    origin
    Show all 10 updates
    1. f28a3fb6 updated to 2c7efddaindex 8a712951

      1 source commit

      1. 2c7efdda
        Problem: Intelligent-Tiering pages remain outside the shared read family

        ListBucketIntelligentTieringConfigurations is tracked by the pinned S3 model but lacks executable client and signed-corpus coverage. Implementing its continuation, bounded XML decoding, composable ownership, and evidence registration independently would repeat the same paginated read mechanics and leave future operations vulnerable to drift.

        Solution: Qualify Intelligent-Tiering through the paginated REST/XML family

        Add the model-verified Intelligent-Tiering page decoder and provider-centric synchronous and composable calls over the shared state machine. Register reviewed absence, continuation, exclusion, signed-socket, generated-negative, qualification, coverage, and documentation evidence while keeping page traversal caller-owned and preserving existing ownership, cancellation, bounds, and no-retry semantics.

    2. 2c7efdda updated to 77811f75index 20236e51

      1 source commit

      1. 77811f75
        Problem: inventory pages remain outside the shared read family

        ListBucketInventoryConfigurations is tracked by the pinned S3 model but has no provider-owned one-page client or executable qualification. Callers cannot use the reviewed paginated configuration-read state machine for inventory pages, and the coverage ledger remains partial.

        Solution: qualify inventory pages through the shared family

        Add the strict page projection, exact low-level request and decoder, provider-owned synchronous and composable overloads, and typed Finish over the existing bounded state machine. Record the reviewed decisions in the operation manifest and regenerate model-derived negative XML, signed-socket, coverage, test-registration, and documentation evidence.

    3. 77811f75 updated to 21a19c53index 6c16e56d

      1 source commit

      1. 21a19c53
        Problem: bucket metadata reads remain outside the shared read family

        GetBucketMetadataConfiguration is inventoried but lacks an executable provider-owned client, strict complete model projection, and generated qualification evidence. Callers cannot compose or synchronously read the current metadata destination and table state through the shared owner-driven transport, and the coverage ledger remains partial.

        Solution: qualify the complete bucket metadata read

        Add strict model-preserving metadata result types and decoding, exact low-level request, execute, and composable forms, and provider-owned limited, restart, Finish, and synchronous overloads over Bounded_REST_XML_Reads. Record reviewed endpoint and error policy and generate signed and negative evidence for the complete reachable shape graph.

    4. 21a19c53 updated to d2781ffcindex cf3488ae

      1 source commit

      1. d2781ffc
        Problem: Object annotation listings lack a qualified provider-owned client path

        The pinned S3 model tracks ListObjectAnnotations, but the client and signed
        corpus remain partial. The shared paginated REST/XML family only accepts
        flattened items and fixed page scalars, which would otherwise force this
        wrapper- and header-bearing object read to duplicate transport ownership and
        qualification plumbing.

        Solution: add ListObjectAnnotations through the shared read families

        Extend the internal paginated and bounded read families with explicit reviewed
        container, scalar, and same-response header hooks. Add the strict annotation
        codec, exact low-level preparation, provider-owned synchronous and composable
        forms, model-generated negative cases, and signed socket qualification. Update
        the evidence registry and greedy URI-label verifier while preserving caller-
        selected limits, read-only certainty, restart ownership, and typed Finish.

    5. d2781ffc updated to 6fb5f95aindex 84198948

      2 source commits

      1. d5d4cbb2
        Problem: Repetitive mutation mechanics slow S3 client coverage

        Each REST/XML mutation currently duplicates one-shot source handling, bounded response collection, child drain, cancellation, restart, and Finish mechanics. The signed-socket registry also assumes bodyless requests, so new mutation qualification requires bespoke synchronization and cannot verify the exact signed payload hash.

        Solution: Add shared nonreplaying mutation infrastructure

        Introduce an internal generic that centralizes only transport and ownership mechanics while leaving serialization, admission classification, reconciliation, and public policy in reviewed provider actuals. Extend the pinned-model signed-socket generator to derive and verify request bodies and payload hashes, reject collisions with derived headers, and support mutation plans without response-XML negative templates.

      2. 6fb5f95a
        Problem: Metrics replacement remains outside the qualified client surface

        PutBucketMetricsConfiguration has no exact prepared, synchronous, or provider-owned composable API despite its Get/List/Delete siblings being qualified. PutBucketReplication also retains a private copy of the same mutation lifetime machinery, leaving the new family without a retrospective equivalence canary.

        Solution: Qualify metrics replacement through the shared family

        Add strict bounded metrics serialization, exact id-query preparation, one-shot low-level execution, and provider-centric Set_Metrics_Configuration overloads with typed certainty and caller-directed reconciliation. Migrate PutBucketReplication onto the shared family without changing its public API or normalization, and add model-derived deterministic and signed-socket evidence for low-level, synchronous, composable, restart, duplicate-header, and bounded-response lanes.

    6. 6fb5f95a updated to 1193aa33index d0d3e6ee

      1 source commit

      1. 1193aa33
        Problem: Analytics replacement remains outside the qualified composable surface

        PutBucketAnalyticsConfiguration has no provider-owned operation, typed Finish path, or executable signed qualification. Callers cannot compose analytics replacement with the existing Get/List/Delete vocabulary, and the shared mutation preparer incorrectly conflates a required present-empty configuration id with absence.

        Solution: Route analytics replacement through the shared mutation family

        Add exact bounded analytics serialization, operation-specific low-level preparation and pre-admission checks, and provider-owned limited, restartable, typed, and synchronous forms over the existing one-shot REST/XML mutation state machine. Preserve conservative admission certainty and read-only reconciliation, retain present-empty modeled ids, and register deterministic and signed-socket evidence without introducing execution-policy defaults.

    7. 1193aa33 updated to 0bf21f8cindex 033ebb98

      1 source commit

      1. 0bf21f8c
        Problem: PutBucketIntelligentTieringConfiguration lacks complete client coverage

        Callers cannot use the intelligent-tiering configuration mutation through the provider-owned synchronous and composable API, and sibling analytics and metrics mutation qualifiers collapse conclusive authentication, authorization, and absence failures into a generic invalid-request result.

        Solution: add the shared-family mutation operation and preserve typed rejections

        Add strict intelligent-tiering XML serialization, low-level preparation, provider-centric synchronous/composable/restart/Finish lanes over the shared mutation state machine, signed and deterministic executable evidence, and generated coverage registration. Keep the request body one-shot and non-rewindable, prohibit replay, preserve conservative outcome certainty, and correct the sibling signed qualifiers to retain conclusive typed failures.

    8. 0bf21f8c updated to 76e39f44index 8b626e55

      8 source commits

      1. 08c974f8
        Problem: S3 operation scaffolding cannot emit strict model-derived codecs

        Future routine operations still require handwritten XML structure validation and lack one lossless operation-level inventory of implementation mode, generation eligibility, and executable evidence. That keeps review spread across many files and risks treating declarations as coverage.

        Solution: add strict codec generation and a reviewed generation registry

        Upgrade the 116-operation registry without changing existing Ada implementations, add deterministic inventory and documentation outputs, introduce a private shared strict XML runtime with caller-owned limits, and teach the uv scaffold to emit guarded generated descriptors only after human decisions are resolved.

      2. b2dd0fa6
        Problem: generated XML mechanics lack a non-destructive semantic canary

        A prospective generator can be deterministic while still drifting from the reviewed provider API, strict Website codec, typed Finish lanes, or executable evidence. Replacing the existing handwritten operation would hide that distinction.

        Solution: verify prospective Website output against authoritative sources

        Generate a normalized GetBucketWebsite canary that hashes the untouched handwritten implementation, compares model, XML-negative, signed-socket, API, lifecycle, and coverage evidence, and records prospective descriptor hashes without committing or adopting that descriptor.

      3. 634f81b8
        Problem: Signed read qualification repeats operation-lifetime mechanics

        Each bounded REST/XML read carries another Ada executable that repeats environment decoding, client setup, completion-set driving, typed Finish, restart, cancellation drain, and shutdown. This expands handwritten review surface even though only preparation and typed result observation differ by operation.

        Solution: Add a shared typed signed-socket read driver

        Introduce a test-only generic that owns the invariant low-level, synchronous, composable, restart, cancellation/drain/reuse, and cleanup lanes while retaining operation-specific typed callbacks. Allow the loopback runner to target a prospective adapter without replacing the committed authoritative adapter, and document the generated-versus-human boundary.

      4. 197ab0e4
        Problem: Deprecated S3 reads appear eligible for generation

        The retrospective registry marks GetBucketLifecycle and GetBucketNotification as generator candidates even though the pinned model deprecates them and the maintained compatibility contract names their Configuration replacements. A scaffold could therefore create public APIs the repository intentionally excludes.

        Solution: Record the deprecated-operation exclusions

        Mark both legacy reads ineligible, remove their unresolved generation blocks, and regenerate the inventory, counts, and documentation without changing their preserved partial coverage state or generated-model provenance.

      5. 490d7660
        Problem: Generated XML codecs omit modeled string patterns

        New S3 operations can carry Botocore string-pattern constraints that the strict descriptor runtime does not represent. Silently accepting those values would make generated codecs weaker than the pinned model and could admit malformed provider responses.

        Solution: Add fail-closed exact pattern validation

        Teach the generator and shared strict runtime to validate the modeled S3 and S3 Express bucket ARN domain, reject all unsupported pattern forms during generation, document the boundary, and cover the directory-bucket descriptor plus the no-enum generation edge case. Regenerated canary evidence records the expanded strict contract without replacing any handwritten operation.

      6. b17b81cd
        Problem: Generated provider glue risks owning handwritten packages

        New operations must add public declarations and bodies to provider-centric parent packages, but treating those large packages as generated output would make existing reviewed operations vulnerable to unrelated churn.

        Solution: Materialize only delimited generated regions

        Add a deterministic source-region materializer that inserts or replaces one uniquely balanced generated block while preserving every surrounding byte. Reject missing anchors, duplicate markers, and unbalanced regions, cover insertion and replacement with negative oracles, and document the handwritten/generated ownership boundary.

      7. 5d8a6921
        Problem: Paginated reads cannot carry collection policy

        The bounded REST/XML read family transports document limits but has no place for the distinct caller-selected collection limit required by generated list codecs. Copying its owner-driven lifecycle into every list operation would preserve the repeated mechanical work the automation is intended to remove.

        Solution: Add a shared paginated read family

        Add one provider-neutral family that retains the bounded response sink, child lifetime, cancellation, drain, restart, exception, and typed Finish behavior while carrying an explicit collection limit into response decoding. It introduces no defaults and changes no existing operation.

      8. 76e39f44
        Problem: Directory bucket reads still require handwritten client slices

        ListDirectoryBuckets is absent from the client even though its request and strict XML response mechanics are derivable from the pinned Botocore model. Implementing it by hand would repeat low-level, provider, lifecycle, corpus, socket, documentation, and coverage bookkeeping across another large review surface.

        Solution: Generate and qualify ListDirectoryBuckets through the paginated read family

        Extend the authoritative generator to materialize exact low-level and provider-owned Ada regions, a strict bounded XML codec, and deterministic evidence from reviewed manifest decisions. Add the shared typed signed-socket adapter, verify mismatched prepared operations before admission, preserve caller-selected limits and owner-driven restart/cancellation semantics, and register executable coverage without claiming backend or server support.

    9. 76e39f44 updated to eb2e25e9index fd29616c

      2 source commits

      1. 44636497
        Problem: Generated mutation codecs repeat bounded XML mechanics

        New S3 mutation serializers need strict escaping and caller-selected document, depth, element, and text enforcement. Repeating that machinery in every operation would keep the review surface large and could let model changes silently retain stale typed projections.

        Solution: Add a shared bounded XML writer and model-bound serializer projections

        The internal writer centralizes escaping and explicit resource-limit accounting without defaults. The generator now verifies full reachable-shape digests before emitting reviewed Inventory, Logging, and Website request projections, with deterministic negative oracles and maintainer documentation.

      2. eb2e25e9
        Problem: Routine bucket configuration mutations repeat client mechanics

        New REST/XML configuration mutations still require large handwritten low-level, provider, serializer, and signed-socket slices even when their transport and lifecycle semantics match the reviewed shared family. This keeps the remaining S3 backlog expensive to implement and review.

        Solution: Generate three reviewed configuration mutations

        Generate PutBucketInventoryConfiguration, PutBucketLogging, and PutBucketWebsite serializers, exact prepared-operation bindings, provider-centric synchronous/composable/restart APIs, typed Finish results, and typed qualification adapters from one authoritative tool. Keep certainty, no-replay, reconciliation, ownership, cross-field, checksum, and compatibility decisions explicit in the human-owned registry while expanding one reviewed fixture into the common signed matrix.

    10. eb2e25e9 updated to 5eaf79cfindex 7a754917

      1 source commit

      1. 5eaf79cf
        Problem: ACL mutations still require handwritten operation plumbing

        Future S3 ACL mutation coverage repeats model-derived request serialization, prepared-request binding, provider state-machine glue, and signed-socket qualification. That review surface slows the remaining backlog and risks drift between synchronous, composable, and restart lanes.

        Solution: generate PutBucketAcl from reviewed model and policy inputs

        Extend the deterministic mutation generator with strict ACL XML serialization, modeled headers and checksums, exact-operation admission, provider-centric Set_ACL overloads, typed Finish, and shared qualification evidence. Keep ACL mode selection, certainty, no-replay, reconciliation, cross-field exclusions, and ownership decisions explicit in the human-owned operation manifest.

    Compare source revisions
    Development update

    flyology_object_storage_server 0.1.0-dev

    10 updates: f28a3fb6 through 5eaf79cf

    Supervised S3 server and management console for Flyology Object Storage

    Manifest fields
    origin
    Show all 10 updates
    1. f28a3fb6 updated to 2c7efddaindex 8a712951

      1 source commit

      1. 2c7efdda
        Problem: Intelligent-Tiering pages remain outside the shared read family

        ListBucketIntelligentTieringConfigurations is tracked by the pinned S3 model but lacks executable client and signed-corpus coverage. Implementing its continuation, bounded XML decoding, composable ownership, and evidence registration independently would repeat the same paginated read mechanics and leave future operations vulnerable to drift.

        Solution: Qualify Intelligent-Tiering through the paginated REST/XML family

        Add the model-verified Intelligent-Tiering page decoder and provider-centric synchronous and composable calls over the shared state machine. Register reviewed absence, continuation, exclusion, signed-socket, generated-negative, qualification, coverage, and documentation evidence while keeping page traversal caller-owned and preserving existing ownership, cancellation, bounds, and no-retry semantics.

    2. 2c7efdda updated to 77811f75index 20236e51

      1 source commit

      1. 77811f75
        Problem: inventory pages remain outside the shared read family

        ListBucketInventoryConfigurations is tracked by the pinned S3 model but has no provider-owned one-page client or executable qualification. Callers cannot use the reviewed paginated configuration-read state machine for inventory pages, and the coverage ledger remains partial.

        Solution: qualify inventory pages through the shared family

        Add the strict page projection, exact low-level request and decoder, provider-owned synchronous and composable overloads, and typed Finish over the existing bounded state machine. Record the reviewed decisions in the operation manifest and regenerate model-derived negative XML, signed-socket, coverage, test-registration, and documentation evidence.

    3. 77811f75 updated to 21a19c53index 6c16e56d

      1 source commit

      1. 21a19c53
        Problem: bucket metadata reads remain outside the shared read family

        GetBucketMetadataConfiguration is inventoried but lacks an executable provider-owned client, strict complete model projection, and generated qualification evidence. Callers cannot compose or synchronously read the current metadata destination and table state through the shared owner-driven transport, and the coverage ledger remains partial.

        Solution: qualify the complete bucket metadata read

        Add strict model-preserving metadata result types and decoding, exact low-level request, execute, and composable forms, and provider-owned limited, restart, Finish, and synchronous overloads over Bounded_REST_XML_Reads. Record reviewed endpoint and error policy and generate signed and negative evidence for the complete reachable shape graph.

    4. 21a19c53 updated to d2781ffcindex cf3488ae

      1 source commit

      1. d2781ffc
        Problem: Object annotation listings lack a qualified provider-owned client path

        The pinned S3 model tracks ListObjectAnnotations, but the client and signed
        corpus remain partial. The shared paginated REST/XML family only accepts
        flattened items and fixed page scalars, which would otherwise force this
        wrapper- and header-bearing object read to duplicate transport ownership and
        qualification plumbing.

        Solution: add ListObjectAnnotations through the shared read families

        Extend the internal paginated and bounded read families with explicit reviewed
        container, scalar, and same-response header hooks. Add the strict annotation
        codec, exact low-level preparation, provider-owned synchronous and composable
        forms, model-generated negative cases, and signed socket qualification. Update
        the evidence registry and greedy URI-label verifier while preserving caller-
        selected limits, read-only certainty, restart ownership, and typed Finish.

    5. d2781ffc updated to 6fb5f95aindex 84198948

      2 source commits

      1. d5d4cbb2
        Problem: Repetitive mutation mechanics slow S3 client coverage

        Each REST/XML mutation currently duplicates one-shot source handling, bounded response collection, child drain, cancellation, restart, and Finish mechanics. The signed-socket registry also assumes bodyless requests, so new mutation qualification requires bespoke synchronization and cannot verify the exact signed payload hash.

        Solution: Add shared nonreplaying mutation infrastructure

        Introduce an internal generic that centralizes only transport and ownership mechanics while leaving serialization, admission classification, reconciliation, and public policy in reviewed provider actuals. Extend the pinned-model signed-socket generator to derive and verify request bodies and payload hashes, reject collisions with derived headers, and support mutation plans without response-XML negative templates.

      2. 6fb5f95a
        Problem: Metrics replacement remains outside the qualified client surface

        PutBucketMetricsConfiguration has no exact prepared, synchronous, or provider-owned composable API despite its Get/List/Delete siblings being qualified. PutBucketReplication also retains a private copy of the same mutation lifetime machinery, leaving the new family without a retrospective equivalence canary.

        Solution: Qualify metrics replacement through the shared family

        Add strict bounded metrics serialization, exact id-query preparation, one-shot low-level execution, and provider-centric Set_Metrics_Configuration overloads with typed certainty and caller-directed reconciliation. Migrate PutBucketReplication onto the shared family without changing its public API or normalization, and add model-derived deterministic and signed-socket evidence for low-level, synchronous, composable, restart, duplicate-header, and bounded-response lanes.

    6. 6fb5f95a updated to 1193aa33index d0d3e6ee

      1 source commit

      1. 1193aa33
        Problem: Analytics replacement remains outside the qualified composable surface

        PutBucketAnalyticsConfiguration has no provider-owned operation, typed Finish path, or executable signed qualification. Callers cannot compose analytics replacement with the existing Get/List/Delete vocabulary, and the shared mutation preparer incorrectly conflates a required present-empty configuration id with absence.

        Solution: Route analytics replacement through the shared mutation family

        Add exact bounded analytics serialization, operation-specific low-level preparation and pre-admission checks, and provider-owned limited, restartable, typed, and synchronous forms over the existing one-shot REST/XML mutation state machine. Preserve conservative admission certainty and read-only reconciliation, retain present-empty modeled ids, and register deterministic and signed-socket evidence without introducing execution-policy defaults.

    7. 1193aa33 updated to 0bf21f8cindex 033ebb98

      1 source commit

      1. 0bf21f8c
        Problem: PutBucketIntelligentTieringConfiguration lacks complete client coverage

        Callers cannot use the intelligent-tiering configuration mutation through the provider-owned synchronous and composable API, and sibling analytics and metrics mutation qualifiers collapse conclusive authentication, authorization, and absence failures into a generic invalid-request result.

        Solution: add the shared-family mutation operation and preserve typed rejections

        Add strict intelligent-tiering XML serialization, low-level preparation, provider-centric synchronous/composable/restart/Finish lanes over the shared mutation state machine, signed and deterministic executable evidence, and generated coverage registration. Keep the request body one-shot and non-rewindable, prohibit replay, preserve conservative outcome certainty, and correct the sibling signed qualifiers to retain conclusive typed failures.

    8. 0bf21f8c updated to 76e39f44index 8b626e55

      8 source commits

      1. 08c974f8
        Problem: S3 operation scaffolding cannot emit strict model-derived codecs

        Future routine operations still require handwritten XML structure validation and lack one lossless operation-level inventory of implementation mode, generation eligibility, and executable evidence. That keeps review spread across many files and risks treating declarations as coverage.

        Solution: add strict codec generation and a reviewed generation registry

        Upgrade the 116-operation registry without changing existing Ada implementations, add deterministic inventory and documentation outputs, introduce a private shared strict XML runtime with caller-owned limits, and teach the uv scaffold to emit guarded generated descriptors only after human decisions are resolved.

      2. b2dd0fa6
        Problem: generated XML mechanics lack a non-destructive semantic canary

        A prospective generator can be deterministic while still drifting from the reviewed provider API, strict Website codec, typed Finish lanes, or executable evidence. Replacing the existing handwritten operation would hide that distinction.

        Solution: verify prospective Website output against authoritative sources

        Generate a normalized GetBucketWebsite canary that hashes the untouched handwritten implementation, compares model, XML-negative, signed-socket, API, lifecycle, and coverage evidence, and records prospective descriptor hashes without committing or adopting that descriptor.

      3. 634f81b8
        Problem: Signed read qualification repeats operation-lifetime mechanics

        Each bounded REST/XML read carries another Ada executable that repeats environment decoding, client setup, completion-set driving, typed Finish, restart, cancellation drain, and shutdown. This expands handwritten review surface even though only preparation and typed result observation differ by operation.

        Solution: Add a shared typed signed-socket read driver

        Introduce a test-only generic that owns the invariant low-level, synchronous, composable, restart, cancellation/drain/reuse, and cleanup lanes while retaining operation-specific typed callbacks. Allow the loopback runner to target a prospective adapter without replacing the committed authoritative adapter, and document the generated-versus-human boundary.

      4. 197ab0e4
        Problem: Deprecated S3 reads appear eligible for generation

        The retrospective registry marks GetBucketLifecycle and GetBucketNotification as generator candidates even though the pinned model deprecates them and the maintained compatibility contract names their Configuration replacements. A scaffold could therefore create public APIs the repository intentionally excludes.

        Solution: Record the deprecated-operation exclusions

        Mark both legacy reads ineligible, remove their unresolved generation blocks, and regenerate the inventory, counts, and documentation without changing their preserved partial coverage state or generated-model provenance.

      5. 490d7660
        Problem: Generated XML codecs omit modeled string patterns

        New S3 operations can carry Botocore string-pattern constraints that the strict descriptor runtime does not represent. Silently accepting those values would make generated codecs weaker than the pinned model and could admit malformed provider responses.

        Solution: Add fail-closed exact pattern validation

        Teach the generator and shared strict runtime to validate the modeled S3 and S3 Express bucket ARN domain, reject all unsupported pattern forms during generation, document the boundary, and cover the directory-bucket descriptor plus the no-enum generation edge case. Regenerated canary evidence records the expanded strict contract without replacing any handwritten operation.

      6. b17b81cd
        Problem: Generated provider glue risks owning handwritten packages

        New operations must add public declarations and bodies to provider-centric parent packages, but treating those large packages as generated output would make existing reviewed operations vulnerable to unrelated churn.

        Solution: Materialize only delimited generated regions

        Add a deterministic source-region materializer that inserts or replaces one uniquely balanced generated block while preserving every surrounding byte. Reject missing anchors, duplicate markers, and unbalanced regions, cover insertion and replacement with negative oracles, and document the handwritten/generated ownership boundary.

      7. 5d8a6921
        Problem: Paginated reads cannot carry collection policy

        The bounded REST/XML read family transports document limits but has no place for the distinct caller-selected collection limit required by generated list codecs. Copying its owner-driven lifecycle into every list operation would preserve the repeated mechanical work the automation is intended to remove.

        Solution: Add a shared paginated read family

        Add one provider-neutral family that retains the bounded response sink, child lifetime, cancellation, drain, restart, exception, and typed Finish behavior while carrying an explicit collection limit into response decoding. It introduces no defaults and changes no existing operation.

      8. 76e39f44
        Problem: Directory bucket reads still require handwritten client slices

        ListDirectoryBuckets is absent from the client even though its request and strict XML response mechanics are derivable from the pinned Botocore model. Implementing it by hand would repeat low-level, provider, lifecycle, corpus, socket, documentation, and coverage bookkeeping across another large review surface.

        Solution: Generate and qualify ListDirectoryBuckets through the paginated read family

        Extend the authoritative generator to materialize exact low-level and provider-owned Ada regions, a strict bounded XML codec, and deterministic evidence from reviewed manifest decisions. Add the shared typed signed-socket adapter, verify mismatched prepared operations before admission, preserve caller-selected limits and owner-driven restart/cancellation semantics, and register executable coverage without claiming backend or server support.

    9. 76e39f44 updated to eb2e25e9index fd29616c

      2 source commits

      1. 44636497
        Problem: Generated mutation codecs repeat bounded XML mechanics

        New S3 mutation serializers need strict escaping and caller-selected document, depth, element, and text enforcement. Repeating that machinery in every operation would keep the review surface large and could let model changes silently retain stale typed projections.

        Solution: Add a shared bounded XML writer and model-bound serializer projections

        The internal writer centralizes escaping and explicit resource-limit accounting without defaults. The generator now verifies full reachable-shape digests before emitting reviewed Inventory, Logging, and Website request projections, with deterministic negative oracles and maintainer documentation.

      2. eb2e25e9
        Problem: Routine bucket configuration mutations repeat client mechanics

        New REST/XML configuration mutations still require large handwritten low-level, provider, serializer, and signed-socket slices even when their transport and lifecycle semantics match the reviewed shared family. This keeps the remaining S3 backlog expensive to implement and review.

        Solution: Generate three reviewed configuration mutations

        Generate PutBucketInventoryConfiguration, PutBucketLogging, and PutBucketWebsite serializers, exact prepared-operation bindings, provider-centric synchronous/composable/restart APIs, typed Finish results, and typed qualification adapters from one authoritative tool. Keep certainty, no-replay, reconciliation, ownership, cross-field, checksum, and compatibility decisions explicit in the human-owned registry while expanding one reviewed fixture into the common signed matrix.

    10. eb2e25e9 updated to 5eaf79cfindex 7a754917

      1 source commit

      1. 5eaf79cf
        Problem: ACL mutations still require handwritten operation plumbing

        Future S3 ACL mutation coverage repeats model-derived request serialization, prepared-request binding, provider state-machine glue, and signed-socket qualification. That review surface slows the remaining backlog and risks drift between synchronous, composable, and restart lanes.

        Solution: generate PutBucketAcl from reviewed model and policy inputs

        Extend the deterministic mutation generator with strict ACL XML serialization, modeled headers and checksums, exact-operation admission, provider-centric Set_ACL overloads, typed Finish, and shared qualification evidence. Keep ACL mode selection, certainty, no-replay, reconciliation, cross-field exclusions, and ownership decisions explicit in the human-owned operation manifest.

    Compare source revisions
    Development update

    flyology_object_storage_sqlite 0.1.0-dev

    10 updates: f28a3fb6 through 5eaf79cf

    SQLite catalog backend for Flyology Object Storage

    Manifest fields
    origin
    Show all 10 updates
    1. f28a3fb6 updated to 2c7efddaindex 8a712951

      1 source commit

      1. 2c7efdda
        Problem: Intelligent-Tiering pages remain outside the shared read family

        ListBucketIntelligentTieringConfigurations is tracked by the pinned S3 model but lacks executable client and signed-corpus coverage. Implementing its continuation, bounded XML decoding, composable ownership, and evidence registration independently would repeat the same paginated read mechanics and leave future operations vulnerable to drift.

        Solution: Qualify Intelligent-Tiering through the paginated REST/XML family

        Add the model-verified Intelligent-Tiering page decoder and provider-centric synchronous and composable calls over the shared state machine. Register reviewed absence, continuation, exclusion, signed-socket, generated-negative, qualification, coverage, and documentation evidence while keeping page traversal caller-owned and preserving existing ownership, cancellation, bounds, and no-retry semantics.

    2. 2c7efdda updated to 77811f75index 20236e51

      1 source commit

      1. 77811f75
        Problem: inventory pages remain outside the shared read family

        ListBucketInventoryConfigurations is tracked by the pinned S3 model but has no provider-owned one-page client or executable qualification. Callers cannot use the reviewed paginated configuration-read state machine for inventory pages, and the coverage ledger remains partial.

        Solution: qualify inventory pages through the shared family

        Add the strict page projection, exact low-level request and decoder, provider-owned synchronous and composable overloads, and typed Finish over the existing bounded state machine. Record the reviewed decisions in the operation manifest and regenerate model-derived negative XML, signed-socket, coverage, test-registration, and documentation evidence.

    3. 77811f75 updated to 21a19c53index 6c16e56d

      1 source commit

      1. 21a19c53
        Problem: bucket metadata reads remain outside the shared read family

        GetBucketMetadataConfiguration is inventoried but lacks an executable provider-owned client, strict complete model projection, and generated qualification evidence. Callers cannot compose or synchronously read the current metadata destination and table state through the shared owner-driven transport, and the coverage ledger remains partial.

        Solution: qualify the complete bucket metadata read

        Add strict model-preserving metadata result types and decoding, exact low-level request, execute, and composable forms, and provider-owned limited, restart, Finish, and synchronous overloads over Bounded_REST_XML_Reads. Record reviewed endpoint and error policy and generate signed and negative evidence for the complete reachable shape graph.

    4. 21a19c53 updated to d2781ffcindex cf3488ae

      1 source commit

      1. d2781ffc
        Problem: Object annotation listings lack a qualified provider-owned client path

        The pinned S3 model tracks ListObjectAnnotations, but the client and signed
        corpus remain partial. The shared paginated REST/XML family only accepts
        flattened items and fixed page scalars, which would otherwise force this
        wrapper- and header-bearing object read to duplicate transport ownership and
        qualification plumbing.

        Solution: add ListObjectAnnotations through the shared read families

        Extend the internal paginated and bounded read families with explicit reviewed
        container, scalar, and same-response header hooks. Add the strict annotation
        codec, exact low-level preparation, provider-owned synchronous and composable
        forms, model-generated negative cases, and signed socket qualification. Update
        the evidence registry and greedy URI-label verifier while preserving caller-
        selected limits, read-only certainty, restart ownership, and typed Finish.

    5. d2781ffc updated to 6fb5f95aindex 84198948

      2 source commits

      1. d5d4cbb2
        Problem: Repetitive mutation mechanics slow S3 client coverage

        Each REST/XML mutation currently duplicates one-shot source handling, bounded response collection, child drain, cancellation, restart, and Finish mechanics. The signed-socket registry also assumes bodyless requests, so new mutation qualification requires bespoke synchronization and cannot verify the exact signed payload hash.

        Solution: Add shared nonreplaying mutation infrastructure

        Introduce an internal generic that centralizes only transport and ownership mechanics while leaving serialization, admission classification, reconciliation, and public policy in reviewed provider actuals. Extend the pinned-model signed-socket generator to derive and verify request bodies and payload hashes, reject collisions with derived headers, and support mutation plans without response-XML negative templates.

      2. 6fb5f95a
        Problem: Metrics replacement remains outside the qualified client surface

        PutBucketMetricsConfiguration has no exact prepared, synchronous, or provider-owned composable API despite its Get/List/Delete siblings being qualified. PutBucketReplication also retains a private copy of the same mutation lifetime machinery, leaving the new family without a retrospective equivalence canary.

        Solution: Qualify metrics replacement through the shared family

        Add strict bounded metrics serialization, exact id-query preparation, one-shot low-level execution, and provider-centric Set_Metrics_Configuration overloads with typed certainty and caller-directed reconciliation. Migrate PutBucketReplication onto the shared family without changing its public API or normalization, and add model-derived deterministic and signed-socket evidence for low-level, synchronous, composable, restart, duplicate-header, and bounded-response lanes.

    6. 6fb5f95a updated to 1193aa33index d0d3e6ee

      1 source commit

      1. 1193aa33
        Problem: Analytics replacement remains outside the qualified composable surface

        PutBucketAnalyticsConfiguration has no provider-owned operation, typed Finish path, or executable signed qualification. Callers cannot compose analytics replacement with the existing Get/List/Delete vocabulary, and the shared mutation preparer incorrectly conflates a required present-empty configuration id with absence.

        Solution: Route analytics replacement through the shared mutation family

        Add exact bounded analytics serialization, operation-specific low-level preparation and pre-admission checks, and provider-owned limited, restartable, typed, and synchronous forms over the existing one-shot REST/XML mutation state machine. Preserve conservative admission certainty and read-only reconciliation, retain present-empty modeled ids, and register deterministic and signed-socket evidence without introducing execution-policy defaults.

    7. 1193aa33 updated to 0bf21f8cindex 033ebb98

      1 source commit

      1. 0bf21f8c
        Problem: PutBucketIntelligentTieringConfiguration lacks complete client coverage

        Callers cannot use the intelligent-tiering configuration mutation through the provider-owned synchronous and composable API, and sibling analytics and metrics mutation qualifiers collapse conclusive authentication, authorization, and absence failures into a generic invalid-request result.

        Solution: add the shared-family mutation operation and preserve typed rejections

        Add strict intelligent-tiering XML serialization, low-level preparation, provider-centric synchronous/composable/restart/Finish lanes over the shared mutation state machine, signed and deterministic executable evidence, and generated coverage registration. Keep the request body one-shot and non-rewindable, prohibit replay, preserve conservative outcome certainty, and correct the sibling signed qualifiers to retain conclusive typed failures.

    8. 0bf21f8c updated to 76e39f44index 8b626e55

      8 source commits

      1. 08c974f8
        Problem: S3 operation scaffolding cannot emit strict model-derived codecs

        Future routine operations still require handwritten XML structure validation and lack one lossless operation-level inventory of implementation mode, generation eligibility, and executable evidence. That keeps review spread across many files and risks treating declarations as coverage.

        Solution: add strict codec generation and a reviewed generation registry

        Upgrade the 116-operation registry without changing existing Ada implementations, add deterministic inventory and documentation outputs, introduce a private shared strict XML runtime with caller-owned limits, and teach the uv scaffold to emit guarded generated descriptors only after human decisions are resolved.

      2. b2dd0fa6
        Problem: generated XML mechanics lack a non-destructive semantic canary

        A prospective generator can be deterministic while still drifting from the reviewed provider API, strict Website codec, typed Finish lanes, or executable evidence. Replacing the existing handwritten operation would hide that distinction.

        Solution: verify prospective Website output against authoritative sources

        Generate a normalized GetBucketWebsite canary that hashes the untouched handwritten implementation, compares model, XML-negative, signed-socket, API, lifecycle, and coverage evidence, and records prospective descriptor hashes without committing or adopting that descriptor.

      3. 634f81b8
        Problem: Signed read qualification repeats operation-lifetime mechanics

        Each bounded REST/XML read carries another Ada executable that repeats environment decoding, client setup, completion-set driving, typed Finish, restart, cancellation drain, and shutdown. This expands handwritten review surface even though only preparation and typed result observation differ by operation.

        Solution: Add a shared typed signed-socket read driver

        Introduce a test-only generic that owns the invariant low-level, synchronous, composable, restart, cancellation/drain/reuse, and cleanup lanes while retaining operation-specific typed callbacks. Allow the loopback runner to target a prospective adapter without replacing the committed authoritative adapter, and document the generated-versus-human boundary.

      4. 197ab0e4
        Problem: Deprecated S3 reads appear eligible for generation

        The retrospective registry marks GetBucketLifecycle and GetBucketNotification as generator candidates even though the pinned model deprecates them and the maintained compatibility contract names their Configuration replacements. A scaffold could therefore create public APIs the repository intentionally excludes.

        Solution: Record the deprecated-operation exclusions

        Mark both legacy reads ineligible, remove their unresolved generation blocks, and regenerate the inventory, counts, and documentation without changing their preserved partial coverage state or generated-model provenance.

      5. 490d7660
        Problem: Generated XML codecs omit modeled string patterns

        New S3 operations can carry Botocore string-pattern constraints that the strict descriptor runtime does not represent. Silently accepting those values would make generated codecs weaker than the pinned model and could admit malformed provider responses.

        Solution: Add fail-closed exact pattern validation

        Teach the generator and shared strict runtime to validate the modeled S3 and S3 Express bucket ARN domain, reject all unsupported pattern forms during generation, document the boundary, and cover the directory-bucket descriptor plus the no-enum generation edge case. Regenerated canary evidence records the expanded strict contract without replacing any handwritten operation.

      6. b17b81cd
        Problem: Generated provider glue risks owning handwritten packages

        New operations must add public declarations and bodies to provider-centric parent packages, but treating those large packages as generated output would make existing reviewed operations vulnerable to unrelated churn.

        Solution: Materialize only delimited generated regions

        Add a deterministic source-region materializer that inserts or replaces one uniquely balanced generated block while preserving every surrounding byte. Reject missing anchors, duplicate markers, and unbalanced regions, cover insertion and replacement with negative oracles, and document the handwritten/generated ownership boundary.

      7. 5d8a6921
        Problem: Paginated reads cannot carry collection policy

        The bounded REST/XML read family transports document limits but has no place for the distinct caller-selected collection limit required by generated list codecs. Copying its owner-driven lifecycle into every list operation would preserve the repeated mechanical work the automation is intended to remove.

        Solution: Add a shared paginated read family

        Add one provider-neutral family that retains the bounded response sink, child lifetime, cancellation, drain, restart, exception, and typed Finish behavior while carrying an explicit collection limit into response decoding. It introduces no defaults and changes no existing operation.

      8. 76e39f44
        Problem: Directory bucket reads still require handwritten client slices

        ListDirectoryBuckets is absent from the client even though its request and strict XML response mechanics are derivable from the pinned Botocore model. Implementing it by hand would repeat low-level, provider, lifecycle, corpus, socket, documentation, and coverage bookkeeping across another large review surface.

        Solution: Generate and qualify ListDirectoryBuckets through the paginated read family

        Extend the authoritative generator to materialize exact low-level and provider-owned Ada regions, a strict bounded XML codec, and deterministic evidence from reviewed manifest decisions. Add the shared typed signed-socket adapter, verify mismatched prepared operations before admission, preserve caller-selected limits and owner-driven restart/cancellation semantics, and register executable coverage without claiming backend or server support.

    9. 76e39f44 updated to eb2e25e9index fd29616c

      2 source commits

      1. 44636497
        Problem: Generated mutation codecs repeat bounded XML mechanics

        New S3 mutation serializers need strict escaping and caller-selected document, depth, element, and text enforcement. Repeating that machinery in every operation would keep the review surface large and could let model changes silently retain stale typed projections.

        Solution: Add a shared bounded XML writer and model-bound serializer projections

        The internal writer centralizes escaping and explicit resource-limit accounting without defaults. The generator now verifies full reachable-shape digests before emitting reviewed Inventory, Logging, and Website request projections, with deterministic negative oracles and maintainer documentation.

      2. eb2e25e9
        Problem: Routine bucket configuration mutations repeat client mechanics

        New REST/XML configuration mutations still require large handwritten low-level, provider, serializer, and signed-socket slices even when their transport and lifecycle semantics match the reviewed shared family. This keeps the remaining S3 backlog expensive to implement and review.

        Solution: Generate three reviewed configuration mutations

        Generate PutBucketInventoryConfiguration, PutBucketLogging, and PutBucketWebsite serializers, exact prepared-operation bindings, provider-centric synchronous/composable/restart APIs, typed Finish results, and typed qualification adapters from one authoritative tool. Keep certainty, no-replay, reconciliation, ownership, cross-field, checksum, and compatibility decisions explicit in the human-owned registry while expanding one reviewed fixture into the common signed matrix.

    10. eb2e25e9 updated to 5eaf79cfindex 7a754917

      1 source commit

      1. 5eaf79cf
        Problem: ACL mutations still require handwritten operation plumbing

        Future S3 ACL mutation coverage repeats model-derived request serialization, prepared-request binding, provider state-machine glue, and signed-socket qualification. That review surface slows the remaining backlog and risks drift between synchronous, composable, and restart lanes.

        Solution: generate PutBucketAcl from reviewed model and policy inputs

        Extend the deterministic mutation generator with strict ACL XML serialization, modeled headers and checksums, exact-operation admission, provider-centric Set_ACL overloads, typed Finish, and shared qualification evidence. Keep ACL mode selection, certainty, no-replay, reconciliation, cross-field exclusions, and ownership decisions explicit in the human-owned operation manifest.

    Compare source revisions
  9. Development updates

    Development update

    flyology_object_storage 0.1.0-dev

    14 updates: 6ec20483 through f28a3fb6

    S3 client and pluggable object-storage server for Flyology

    Manifest fields
    origin
    Show all 14 updates
    1. 6ec20483 updated to 735fb607index a47fabdb

      25 source commits

      1. 94c0ee9c
        Problem: DeleteBucketLifecycle cannot join composed client workflows

        The exact lifecycle deletion remains limited to blocking convenience and prepared execution. Callers cannot own it in a completion set, preserve typed admission certainty, or reuse its state without a parallel wrapper.

        Solution: add the provider-owned lifecycle deletion operation

        Add the exact low-level initiator and colocated Client.Buckets constructor, operation-last initiation, typed Finish, and synchronous wait over one non-replaying state machine. Gate certainty, prepared-operation identity, physical headers, response bounds, restart, native/lightweight execution, and document the provider inventory.

      2. 571522b3
        Problem: GetBucketPolicyStatus cannot join owner-driven client workflows

        The existing convenience client executes synchronously through its own path, so callers cannot compose the exact signed policy-status read with other provider operations or reuse its operation state safely.

        Solution: colocate a bounded composable policy-status operation

        Add the exact low-level initiator, provider-owned limited constructor, operation-last restart, typed Finish, and typed synchronous wait. Drive the convenience overload through the same bounded state machine, reject malformed singleton headers and over-limit bodies, and qualify the result mapping and native/lightweight socket behavior.

      3. 1c0455b9
        Problem: GetBucketRequestPayment cannot join owner-driven client workflows

        Requester-payment reads are available only through the blocking executor, so structured callers cannot own their deadline, cancellation, operation reuse, typed HTTP outcome, and bounded response lifecycle alongside other work.

        Solution: Colocate a bounded composable requester-payment read

        Add exact prepared-request admission, provider-owned limited construction and operation-last restart, typed Finish and synchronous wait, strict header and response bounds, full normalization and loopback corpora, and maintained API documentation. The established convenience call now waits on the same state machine without adding retry or billing-policy interpretation.

      4. 6befc49a
        Problem: PutBucketRequestPayment cannot join composed client workflows

        The synchronous requester-payment mutation owns no reusable operation, exposes no admission certainty, and cannot participate in a caller-owned completion set.

        Solution: add a non-replaying provider-owned requester-payment operation

        Add the exact low-level initiator, limited constructor, operation-last restart, typed Finish and synchronous wait over one state machine. Own the signed payer bytes through terminal drain, preserve strict response bounds and headers, classify ambiguous outcomes without replay, and gate the contract with certainty, socket, model, documentation and repository checks.

      5. 4664482f
        Problem: PutBucketAbac cannot join composed client workflows

        Callers can only execute PutBucketAbac synchronously, so owner-driven state machines cannot retain typed publication certainty or reconcile ambiguous outcomes without a parallel adapter.

        Solution: add a provider-owned non-replaying ABAC operation

        Expose exact low-level initiation and Client.Buckets limited-constructor, operation-last, typed Finish, and synchronous-wait forms over one state machine. Preserve the serialized status as a one-shot owned source, normalize admission certainty, extend exact-operation and socket corpora, and document the provider inventory and reconciliation contract.

      6. cc04da27
        Problem: PutBucketAccelerateConfiguration cannot compose

        Callers can only execute the acceleration mutation synchronously, so owner-driven workflows cannot preserve typed admission certainty or reconcile ambiguous publication without a separate adapter.

        Solution: add the provider-owned acceleration operation

        Expose the exact one-shot low-level initiator and Client.Buckets limited-constructor, operation-last, typed Finish, and synchronous-wait forms over one state machine. Preserve the model's no-Content-MD5 rule, normalize mutation certainty, extend exact-operation and socket corpora, and document read reconciliation and the updated provider inventory.

      7. 062f8119
        Problem: GetBucketAbac cannot join reconciliation workflows

        Callers can read the optional ABAC state only through a blocking convenience call, so a possibly admitted PutBucketAbac cannot compose its read-only reconciliation with other owner-driven operations. The low-level prepared-request boundary also has no exact reusable initiator for this operation.

        Solution: add one provider-owned bounded GetBucketAbac state machine

        Add the exact Low_Level initiator, limited constructor, operation-last reusable form, typed Finish, and typed synchronous wait in Client.Buckets. Drive the convenience call through that same state machine, preserve the caller-selected XML bound and inherited defaults, and qualify exact operation binding, restart, response normalization, singleton headers, limits, documentation, and ownership without adding retry or helper tasks.

      8. 59ea351b
        Problem: acceleration reads cannot join reconciliation workflows

        Callers that need to reconcile PutBucketAccelerateConfiguration outcomes can only use the blocking convenience read. The exact prepared request has no reusable initiator, so owner-driven workflows cannot compose the bounded response without introducing a parallel state machine.

        Solution: colocate a bounded acceleration read with the Buckets provider

        Add the exact Low_Level initiator, limited constructor, operation-last restart, typed Finish, and typed synchronous wait. Drive the existing convenience overload through the same provider-owned state machine, enforce caller-selected response bounds and singleton headers, and qualify request binding, restart, normalization, malformed headers, and overflow without retries or helper tasks.

      9. 45564e81
        Problem: bucket ACL reads cannot join composed workflows

        GetBucketAcl has a strict typed low-level synchronous client and an authenticated server route, but no provider-owned limited operation. Callers cannot coordinate ACL reads with completion-set workflows without introducing a parallel execution path.

        Solution: colocate a bounded ACL read with the Buckets provider

        Add the exact Low_Level initiator, limited constructor, operation-last restart, typed Finish, and typed synchronous wait. Retain the signed request and bounded response through terminal drain, preserve physical singleton headers and admission diagnostics, and qualify exact binding, restart, normalization, and response limits without retries or helper tasks.

      10. 6b4e9836
        Problem: object ACL reads cannot join composed workflows

        GetObjectAcl has a strict typed synchronous client and authenticated server route, but it lacks the provider-owned limited operation needed by caller-driven completion sets. Callers otherwise need a second API shape and cannot reuse the exact signed request, bounded response, admission certainty, or failure mapping in a larger state machine.

        Solution: colocate a bounded ACL read with the Objects provider

        Add the exact Low_Level sink initiator and Client.Objects limited constructor, operation-last restart, typed Finish, and synchronous wait over one owner-driven state machine. Preserve exact version, requester-pays, expected-owner, singleton-header, caller-limit, cancellation, drain, and no-retry behavior, and gate the surface with preparation, restart, failure-normalization, socket, documentation, and full deterministic corpora.

      11. 22a5e68d
        Problem: metadata-table reads cannot join composed workflows

        GetBucketMetadataTableConfiguration has strict preparation, decoding, and synchronous execution, but no provider-owned limited operation. Callers cannot compose the exact signed request, bounded response snapshot, admission certainty, or typed failure mapping into a larger completion-set state machine.

        Solution: colocate the bounded read with the Buckets provider

        Add the exact Low_Level sink initiator and Client.Buckets limited constructor, operation-last restart, typed Finish, and synchronous wait over one owner-driven state machine. Preserve the opaque provider status, expected-owner projection, singleton diagnostics, caller XML limits, cancellation, drain, and no-retry behavior, and gate the surface with exact preparation, restart, normalization, socket, documentation, and full deterministic corpora.

      12. 0d0dbbac
        Problem: metadata-table creation cannot join composed workflows

        Callers can prepare and synchronously execute CreateBucketMetadataTableConfiguration, but they cannot initiate, restart, or consume it from a provider-owned completion set. The replayable prepared body also obscures the mutation certainty and read-before-retry contract after possible admission.

        Solution: add one-shot provider-owned metadata-table creation

        Move the prepared payload onto the existing non-rewindable owned-source path, add exact low-level admission gating, and colocate the limited constructor, operation-last restart, typed Finish, and typed synchronous wait in Client.Buckets. Preserve signed MD5/checksum and owner projection, expose conservative mutation certainty, require read-only reconciliation for unknown outcomes, and gate ownership, bounds, restart, cross-operation rejection, and the complete certainty matrix.

      13. c457fcd8
        Problem: conditional annotation deletion cannot join composed workflows

        DeleteObjectAnnotation is limited to a synchronous low-level call, so owner-driven object workflows cannot schedule it beside other provider operations or retain typed admission certainty through terminal drain.

        Solution: colocate nonreplaying annotation deletion with objects

        Add an exact low-level initiator and provider-owned constructor, operation-last restart, typed Finish, and synchronous wait over one state machine. Copy all request identity, preserve one-shot mutation semantics, normalize publication certainty conservatively, and gate the API with exhaustive mapping and signed socket coverage.

      14. f1cd6026
        Problem: replication deletion cannot join composed workflows

        DeleteBucketReplication is available only through synchronous convenience calls, so owner-driven callers cannot retain typed admission certainty, reuse an established operation, or compose it with sibling work.

        Solution: colocate composable replication deletion with the bucket provider

        Add the exact low-level initiator and provider-owned limited operation, operation-last initiation, typed Finish, and typed synchronous wait. Drive the convenience form through the same non-replaying state machine and gate its certainty, ownership, bounds, wire behavior, and documentation exhaustively.

      15. 068b0a9a
        Problem: website deletion cannot join composed workflows

        DeleteBucketWebsite is available only through synchronous convenience calls, so owner-driven callers cannot retain typed admission certainty, reuse an established operation, or compose it with sibling work.

        Solution: colocate composable website deletion with the bucket provider

        Add the exact low-level initiator and provider-owned limited operation, operation-last initiation, typed Finish, and typed synchronous wait. Drive the convenience form through the same non-replaying state machine and gate its certainty, ownership, bounds, wire behavior, and documentation exhaustively.

      16. 7fd0ffc1
        Problem: inventory deletion cannot join composed workflows

        DeleteBucketInventoryConfiguration is available only through a blocking convenience call, so callers cannot schedule it with other owner-driven operations or retain typed publication certainty after possible admission.

        Solution: add a provider-owned composable inventory deletion

        Add the exact low-level initiator, limited constructor, operation-last restart, typed Finish and synchronous wait over one non-replaying state machine. Extend identifier-copy, certainty, response-bound, signed socket, verifier, API documentation and compatibility evidence.

      17. d71a924d
        Problem: CreateSession cannot join composed client workflows

        Directory-bucket callers must use a blocking scalar wrapper, cannot schedule the exchange beside other operations, and cannot inspect typed transport failure or admission certainty. The limited zeroizing credentials result also cannot safely live inside reusable operation storage.

        Solution: add a provider-owned composable CreateSession

        Retain the signed request, physically validated response metadata, and bounded raw response until typed Finish constructs credentials exactly once. Add same-name limited and operation-last forms, make both synchronous forms wait on the same state machine, and qualify cancellation, restart, request copying, response bounds, and malformed-response normalization.

      18. 55460971
        Problem: intelligent-tiering deletion cannot join composed workflows

        DeleteBucketIntelligentTieringConfiguration is available only through the synchronous bucket client, so callers cannot place it in a shared completion set or inspect typed admission certainty after an ambiguous mutation result.

        Solution: add provider-owned composable intelligent-tiering deletion

        Add exact low-level initiation, a non-replaying Client.Buckets operation with operation-last restart and typed Finish, and route the synchronous forms through the same state machine. Qualify copied inputs, certainty normalization, response bounds, malformed headers, documentation, and the pinned operation inventory.

      19. 4bf62837
        Problem: analytics deletion cannot join composed workflows

        DeleteBucketAnalyticsConfiguration is available only through the synchronous bucket client, so callers cannot share a completion set or retain typed certainty when deletion may have reached the service.

        Solution: add provider-owned composable analytics deletion

        Add an exact low-level initiator, a non-replaying Client.Buckets operation with copied request inputs, operation-last restart, typed Finish, and a synchronous wait over the same state machine. Extend the pinned verifier, certainty matrix, signed native/lightweight socket corpus, and maintained API documentation.

      20. d50be24c
        Problem: metrics deletion cannot join composed workflows

        DeleteBucketMetricsConfiguration is available only through the synchronous bucket client, so callers cannot share a completion set or preserve typed certainty when the mutation result is ambiguous.

        Solution: add provider-owned composable metrics deletion

        Add exact low-level initiation, a copied-input non-replaying Client.Buckets operation, operation-last restart, typed Finish, and a synchronous wait over the same state machine. Extend pinned canonical-target verification, certainty normalization, signed native/lightweight sockets, bounded-response faults, and maintained documentation.

      21. c12288e0
        Problem: metadata deletion cannot join composed workflows

        DeleteBucketMetadataConfiguration is available only through the synchronous convenience path, so owner-driven callers cannot compose it, inspect typed admission certainty, or reuse the provider operation without a parallel wrapper.

        Solution: add provider-owned composable metadata deletion

        Add the exact Low_Level initiator and Client.Buckets limited constructor, operation-last restart, typed Finish, and typed synchronous wait over one non-replaying state machine. Gate exact operation binding, copied owner input, certainty normalization, bounded physical responses, native/lightweight sockets, model inventory, and API documentation.

      22. b6552934
        Problem: metadata-table deletion cannot join composed workflows

        DeleteBucketMetadataTableConfiguration remains on the last generic blocking bucket-configuration dispatcher. Owner-driven callers cannot compose it, inspect typed admission certainty, or reuse its operation without maintaining a parallel API path.

        Solution: add provider-owned composable metadata-table deletion

        Add the exact Low_Level initiator, limited constructor, operation-last restart, typed Finish, and synchronous wait over one nonreplaying state machine. Rewrite the convenience call through it, gate exact wire and lifecycle behavior, document the provider surface, and remove the now-dead generic dispatcher.

      23. 0cd84b09
        Problem: lifecycle configuration reads remain model-only

        The pinned S3 surface can prepare the request, but callers cannot compose or strictly decode the complete lifecycle configuration graph. This leaves a common retention and cost-control read outside the provider-owned client.

        Solution: add a complete provider-owned lifecycle read

        Add the strict full-graph codec, exact low-level preparation and decoding, limited constructor, reusable initiation, typed Finish, and synchronous wait over one state machine. Gate all 36 modeled members, strict limits, headers, ownership, and native/lightweight execution, and record the client-only coverage boundary.

      24. c361be0d
        Problem: lifecycle configuration writes remain model-only

        The current PutBucketLifecycleConfiguration operation has no exact typed low-level or provider-owned composable client, leaving callers without bounded serialization, request-checksum projection, or mutation certainty.

        Solution: add the complete lifecycle configuration write client

        Serialize the pinned request graph, add explicit low-level and provider-owned one-shot APIs, and qualify model identity, limits, signing, certainty, native/lightweight sockets, documentation, and coverage.

      25. 735fb607
        Problem: Current bucket notification configuration lacks a complete composable client

        The current GetBucketNotificationConfiguration and
        PutBucketNotificationConfiguration operations remain partial in the S3 ledger.
        Callers cannot preserve the full destination and filter graph or use the
        provider-owned limited constructor, reusable initiation, typed Finish, and
        same-state-machine synchronous forms with explicit mutation certainty.

        Solution: Add strict current notification GET and PUT clients

        Add the bounded presence-preserving REST/XML codec, exact signed low-level
        preparation and execution, provider-owned GET and non-replaying PUT state
        machines, typed certainty mapping, deterministic model and socket gates, and
        documented coverage. Keep the deprecated notification operations excluded.

    2. 735fb607 updated to 5876862cindex fc0cd1dc

      1 source commit

      1. 5876862c
        Problem: GetBucketReplication lacks a complete composable client contract

        Callers can prepare only part of the operation and cannot receive the pinned
        replication graph through the provider-owned synchronous and composable state
        machine. The coverage corpus therefore cannot qualify the current modeled
        response, strict bounds, or prepared-operation admission boundary.

        Solution: add the bounded provider-owned replication read

        Add a strict presence-preserving replication XML codec, exact low-level
        preparation and decoding, and synchronous, limited-constructor, reusable, and
        typed Finish forms in Client.Buckets. Gate the complete pinned structural
        graph, signed native/lightweight sockets, normalization, bounds, and coverage,
        and document the prose-only cross-field policy boundary.

    3. 5876862c updated to 0673cdadindex eecf5c64

      1 source commit

      1. 0673cdad
        Problem: PutBucketReplication lacks a typed bounded replacement API

        Clients can read bucket replication configuration but cannot replace the same complete graph through the provider-owned composable boundary. Callers would otherwise have to assemble signing, one-shot body ownership, response bounds, and mutation certainty themselves, risking replay or an unsound definite-outcome classification.

        Solution: Add nonreplaying provider-owned replication replacement

        Serialize the reviewed presence-sensitive replication graph under caller limits, prepare and sign the exact modeled request, and expose low-level, limited-constructor, operation-last, typed Finish, and synchronous forms over one state machine. Add deterministic model/XML/certainty coverage, native and lightweight signed socket evidence, maintained documentation, and coverage bookkeeping.

    4. 0673cdad updated to aff992c0index d1470f67

      5 source commits

      1. ded98183
        Problem: Consumer agent resources lag the shared policy

        This repository is pinned to an older flyology-ada/agents revision, so its generated instructions and installed skills omit the current shared assurance workflows.

        Solution: Update the shared agents dependency

        Advance the lockfile to agents revision aa7c026, reinstall the package graph, and regenerate the Codex instructions.

      2. c268566a
        Merge pull request #1 from flyology-ada/codex/update-agents-aa7c026

        Update shared agents to aa7c026

      3. 4da54070
        Problem: The agents lock retains foundation policy in the TLA+ skill

        This consumer remains pinned to the prior shared agents revision, whose TLA+ workflow includes repository architecture constraints unrelated to using the skill.

        Solution: Update the shared agents lock

        Advance flyology-ada/agents to revision 6a97e7a and record the refined agent-focused TLA+ skill deployment hashes.

      4. 1ec12695
        Merge pull request #2 from flyology-ada/codex/update-agents-6a97e7a

        Update shared agents to 6a97e7a

      5. aff992c0
        Problem: S3 operation qualification repeats unsynchronized mechanics

        Each new S3 operation manually repeats pinned-model parsing, coverage bookkeeping, verifier registration, corpus ordering, and documentation updates. The duplicated inventories have already drifted and make completing the remaining 116-operation surface slower and easier to misclassify.

        Solution: establish a reviewed operation and evidence registry

        Add a human-owned TOML inventory for all 116 pinned operations, a shared uv-driven model/audit/scaffold/qualify tool, generated coverage counts, test registration, and documentation, plus layer-specific executable-evidence checks and negative oracles. Preserve every existing coverage state and corpus order, use GetBucketReplication as the reviewed equivalence canary, and leave legacy Ada implementations unchanged for incremental family migration.

    5. aff992c0 updated to ace67878index 77fa3822

      2 source commits

      1. 06c6331a
        Problem: Bounded REST/XML reads duplicate lifecycle mechanics

        Provider operations repeat response buffering, singleton-header validation, hidden HTTP child drain, cancellation, restart cleanup, and typed terminal storage. This slows operation coverage and lets semantically equivalent read paths drift.

        Solution: Share the owner-driven bounded REST/XML read family

        Add an implementation generic for invariant transport and ownership mechanics, then migrate GetBucketReplication as the retrospective canary. Keep provider-owned public signatures, request preparation, decoding, classification, and synchronous-over-composable behavior unchanged, and record executable shared-family provenance in the operation registry.

      2. ace67878
        Problem: Hosted tests cannot run the uv operation verifier

        The root test gate invokes the generated S3 operation registry checks through uv, but the hosted test jobs do not install uv. Both Linux and macOS therefore fail after a successful Ada build, leaving the automation foundation unqualified.

        Solution: Install and enforce the reviewed uv toolchain in CI

        Install exact uv 0.11.28 through immutable setup-uv v9.0.0 in the integrity and test jobs. Extend workflow policy and its negative oracle so both the action and tool version remain pinned.

    6. ace67878 updated to f1a2a7b7index b8287ca4

      1 source commit

      1. f1a2a7b7
        Problem: Signed S3 qualification repeats model-owned mechanics

        Each bounded REST/XML operation manually duplicates exact HTTP targets, signed headers, malformed XML fixtures, socket sequencing, and test registration. Those copies can drift from the pinned Botocore model and make each operation expensive to qualify.

        Solution: Generate data-driven qualification from reviewed decisions

        Derive signed request plans and routine negative XML cases from the pinned model, run them through a shared uv loopback driver and small typed Ada adapter, and register executable evidence from the operation manifest. GetBucketReplication is the retrospective 23-case equivalence canary, while the prospective metrics query oracle verifies reusable canonical query generation.

    7. f1a2a7b7 updated to f65afbf2index a6c27440

      1 source commit

      1. f65afbf2
        Problem: New bounded S3 reads still repeat qualification mechanics

        The shared bounded REST/XML state machine and operation registry establish reusable transport and model evidence, but the first new operation must prove that reviewed API decisions, generated negative XML, signed requests, coverage registration, and documentation can advance without restoring per-operation shell bookkeeping. GetBucketMetricsConfiguration remains partial and invisible to callers until that path is exercised end to end.

        Solution: qualify GetBucketMetricsConfiguration through the shared family

        Add the strict presence-preserving metrics codec and provider-owned low-level, composable, restart, Finish, and synchronous forms over the shared state machine. Record only reviewed semantics and fixtures in the registry, derive the model-owned request and 17 malformed XML cases, run them through a small typed socket adapter, and make the independent coverage oracle discover test trees instead of a maintained filename list. Preserve explicit caller limits and the model's lack of an inferred filter-cardinality or identifier-content constraint.

    8. f65afbf2 updated to 4e5af762index 51207f33

      1 source commit

      1. 4e5af762
        Problem: named analytics reads lack composable coverage

        GetBucketAnalyticsConfiguration is tracked by the pinned S3 model but has no
        typed provider API or executable client evidence. Callers cannot perform one
        bounded named analytics read through the shared owner-driven state machine,
        and the operation registry therefore retains partial client coverage.

        Solution: qualify analytics reads through the shared REST/XML family

        Add a strict model-aligned analytics codec, exact low-level preparation and
        decoding, and provider-owned limited, restartable, typed Finish, and
        synchronous forms. Register reviewed signed cases and model-derived negative
        XML evidence, regenerate the coverage artifacts, and document the resulting
        client-only compatibility boundary.

    9. 4e5af762 updated to 7cbcb44eindex 826970c6

      1 source commit

      1. 7cbcb44e
        Problem: named Intelligent-Tiering reads lack composable coverage

        GetBucketIntelligentTieringConfiguration is tracked by the pinned S3 model
        but has no typed provider API or executable client evidence. Callers cannot
        perform a bounded named configuration read through the shared owner-driven
        state machine, and registry coverage remains partial.

        Solution: qualify Intelligent-Tiering reads through the shared REST/XML family

        Add a strict model-aligned codec, exact low-level preparation and decoding,
        and provider-owned limited, restartable, typed Finish, and synchronous forms.
        Register reviewed signed cases and model-derived negatives, regenerate
        coverage artifacts, and document client-only compatibility.

    10. 7cbcb44e updated to 9fb63d01index 2fe4325e

      1 source commit

      1. 9fb63d01
        Problem: GetBucketInventoryConfiguration lacks a qualified client surface

        Callers cannot read named S3 inventory configurations through the provider-
        centric synchronous and composable APIs. The coverage registry therefore keeps
        the operation partial even though it belongs to the established bounded
        REST/XML read family.

        Solution: add the typed inventory read through the shared family

        Add the strict complete inventory codec, exact low-level preparation and
        decoding, provider-owned constructor/restart/Finish/synchronous forms, and
        model-derived negative and signed-socket qualification. Record the reviewed
        model decisions and executable evidence without claiming backend, server, or
        external-provider support.

    11. 9fb63d01 updated to 10d46346index 400ea643

      1 source commit

      1. 10d46346
        Problem: GetBucketLogging remains outside the qualified shared read family

        The current development line leaves bucket logging as a partial generated client with no provider-owned composable operation or executable corpus. Its modeled payload also uses a wire-root alias, a nonflattened grant list, and required namespaced attributes that the operation verifier cannot yet qualify without manual negative-case work.

        Solution: Add the strict logging client and extend model-driven qualification

        Add the provider-centric low-level, composable, and synchronous Get_Logging forms over the shared bounded REST/XML read state machine. Decode the complete presence-preserving logging graph, disabled state, exact grantee attributes and enum domains, and modeled errors without adding defaults or replay policy. Extend the uv tool to verify structurally equivalent payload aliases, namespaced attributes, and nonflattened list members, then generate and execute the signed and negative XML evidence and update the coverage and architecture records.

    12. 10d46346 updated to f5618821index d2404a6d

      1 source commit

      1. f5618821
        Problem: GetBucketWebsite remains outside the qualified shared read family

        The public client and signed corpus leave bucket website configuration unreadable, and the model verifier rejects the operation's documented payload alias even though its wire structure matches the reviewed WebsiteConfiguration shape. Repeating another handwritten bounded REST/XML read would also preserve the rollout bottleneck.

        Solution: Add a strict provider-owned website read and model-driven evidence

        Add the presence-preserving Website configuration codec, low-level and provider-owned composable/synchronous calls, generated negative XML and signed-socket qualification, and registry coverage. Verify payload aliases structurally while ignoring documentation-only differences and retaining all wire traits, so the shared bounded read family can qualify the operation without semantic drift.

    13. f5618821 updated to d0fd10d7index fdc77edc

      1 source commit

      1. d0fd10d7
        Problem: Paginated configuration reads repeat an unqualified XML envelope

        The remaining bucket-configuration list operations share strict REST/XML page mechanics, request continuation projection, bounded response ownership, and signed qualification structure. Reimplementing those mechanics operation by operation slows coverage work and risks semantic or evidence drift.

        Solution: Add a shared strict page family and qualify Metrics as its canary

        Add a private paginated REST/XML envelope generic, reuse the reviewed metrics item codec, and expose provider-owned one-page synchronous and composable ListBucketMetricsConfigurations calls over the existing bounded read state machine. Record reviewed manifest decisions and generate the model-derived negative XML, signed socket, coverage, registration, and documentation evidence, while keeping continuation caller-driven and public policy unchanged.

    14. d0fd10d7 updated to f28a3fb6index b79170c4

      1 source commit

      1. f28a3fb6
        Problem: Analytics configuration pages remain outside the shared read family

        ListBucketAnalyticsConfigurations is still represented only by model inventory, so callers lack a qualified one-page provider API and each future implementation risks repeating page-envelope, ownership, and evidence mechanics.

        Solution: Qualify Analytics through the paginated REST/XML family

        Reuse the reviewed analytics item decoder inside the shared strict page envelope, add exact low-level and provider-owned synchronous/composable calls over the existing bounded state machine, and generate the model-derived negative, signed-socket, coverage, registration, and documentation evidence from reviewed manifest decisions.

    Compare source revisions
    Development update

    flyology_object_storage_server 0.1.0-dev

    14 updates: 6ec20483 through f28a3fb6

    Supervised S3 server and management console for Flyology Object Storage

    Manifest fields
    origin
    Show all 14 updates
    1. 6ec20483 updated to 735fb607index a47fabdb

      25 source commits

      1. 94c0ee9c
        Problem: DeleteBucketLifecycle cannot join composed client workflows

        The exact lifecycle deletion remains limited to blocking convenience and prepared execution. Callers cannot own it in a completion set, preserve typed admission certainty, or reuse its state without a parallel wrapper.

        Solution: add the provider-owned lifecycle deletion operation

        Add the exact low-level initiator and colocated Client.Buckets constructor, operation-last initiation, typed Finish, and synchronous wait over one non-replaying state machine. Gate certainty, prepared-operation identity, physical headers, response bounds, restart, native/lightweight execution, and document the provider inventory.

      2. 571522b3
        Problem: GetBucketPolicyStatus cannot join owner-driven client workflows

        The existing convenience client executes synchronously through its own path, so callers cannot compose the exact signed policy-status read with other provider operations or reuse its operation state safely.

        Solution: colocate a bounded composable policy-status operation

        Add the exact low-level initiator, provider-owned limited constructor, operation-last restart, typed Finish, and typed synchronous wait. Drive the convenience overload through the same bounded state machine, reject malformed singleton headers and over-limit bodies, and qualify the result mapping and native/lightweight socket behavior.

      3. 1c0455b9
        Problem: GetBucketRequestPayment cannot join owner-driven client workflows

        Requester-payment reads are available only through the blocking executor, so structured callers cannot own their deadline, cancellation, operation reuse, typed HTTP outcome, and bounded response lifecycle alongside other work.

        Solution: Colocate a bounded composable requester-payment read

        Add exact prepared-request admission, provider-owned limited construction and operation-last restart, typed Finish and synchronous wait, strict header and response bounds, full normalization and loopback corpora, and maintained API documentation. The established convenience call now waits on the same state machine without adding retry or billing-policy interpretation.

      4. 6befc49a
        Problem: PutBucketRequestPayment cannot join composed client workflows

        The synchronous requester-payment mutation owns no reusable operation, exposes no admission certainty, and cannot participate in a caller-owned completion set.

        Solution: add a non-replaying provider-owned requester-payment operation

        Add the exact low-level initiator, limited constructor, operation-last restart, typed Finish and synchronous wait over one state machine. Own the signed payer bytes through terminal drain, preserve strict response bounds and headers, classify ambiguous outcomes without replay, and gate the contract with certainty, socket, model, documentation and repository checks.

      5. 4664482f
        Problem: PutBucketAbac cannot join composed client workflows

        Callers can only execute PutBucketAbac synchronously, so owner-driven state machines cannot retain typed publication certainty or reconcile ambiguous outcomes without a parallel adapter.

        Solution: add a provider-owned non-replaying ABAC operation

        Expose exact low-level initiation and Client.Buckets limited-constructor, operation-last, typed Finish, and synchronous-wait forms over one state machine. Preserve the serialized status as a one-shot owned source, normalize admission certainty, extend exact-operation and socket corpora, and document the provider inventory and reconciliation contract.

      6. cc04da27
        Problem: PutBucketAccelerateConfiguration cannot compose

        Callers can only execute the acceleration mutation synchronously, so owner-driven workflows cannot preserve typed admission certainty or reconcile ambiguous publication without a separate adapter.

        Solution: add the provider-owned acceleration operation

        Expose the exact one-shot low-level initiator and Client.Buckets limited-constructor, operation-last, typed Finish, and synchronous-wait forms over one state machine. Preserve the model's no-Content-MD5 rule, normalize mutation certainty, extend exact-operation and socket corpora, and document read reconciliation and the updated provider inventory.

      7. 062f8119
        Problem: GetBucketAbac cannot join reconciliation workflows

        Callers can read the optional ABAC state only through a blocking convenience call, so a possibly admitted PutBucketAbac cannot compose its read-only reconciliation with other owner-driven operations. The low-level prepared-request boundary also has no exact reusable initiator for this operation.

        Solution: add one provider-owned bounded GetBucketAbac state machine

        Add the exact Low_Level initiator, limited constructor, operation-last reusable form, typed Finish, and typed synchronous wait in Client.Buckets. Drive the convenience call through that same state machine, preserve the caller-selected XML bound and inherited defaults, and qualify exact operation binding, restart, response normalization, singleton headers, limits, documentation, and ownership without adding retry or helper tasks.

      8. 59ea351b
        Problem: acceleration reads cannot join reconciliation workflows

        Callers that need to reconcile PutBucketAccelerateConfiguration outcomes can only use the blocking convenience read. The exact prepared request has no reusable initiator, so owner-driven workflows cannot compose the bounded response without introducing a parallel state machine.

        Solution: colocate a bounded acceleration read with the Buckets provider

        Add the exact Low_Level initiator, limited constructor, operation-last restart, typed Finish, and typed synchronous wait. Drive the existing convenience overload through the same provider-owned state machine, enforce caller-selected response bounds and singleton headers, and qualify request binding, restart, normalization, malformed headers, and overflow without retries or helper tasks.

      9. 45564e81
        Problem: bucket ACL reads cannot join composed workflows

        GetBucketAcl has a strict typed low-level synchronous client and an authenticated server route, but no provider-owned limited operation. Callers cannot coordinate ACL reads with completion-set workflows without introducing a parallel execution path.

        Solution: colocate a bounded ACL read with the Buckets provider

        Add the exact Low_Level initiator, limited constructor, operation-last restart, typed Finish, and typed synchronous wait. Retain the signed request and bounded response through terminal drain, preserve physical singleton headers and admission diagnostics, and qualify exact binding, restart, normalization, and response limits without retries or helper tasks.

      10. 6b4e9836
        Problem: object ACL reads cannot join composed workflows

        GetObjectAcl has a strict typed synchronous client and authenticated server route, but it lacks the provider-owned limited operation needed by caller-driven completion sets. Callers otherwise need a second API shape and cannot reuse the exact signed request, bounded response, admission certainty, or failure mapping in a larger state machine.

        Solution: colocate a bounded ACL read with the Objects provider

        Add the exact Low_Level sink initiator and Client.Objects limited constructor, operation-last restart, typed Finish, and synchronous wait over one owner-driven state machine. Preserve exact version, requester-pays, expected-owner, singleton-header, caller-limit, cancellation, drain, and no-retry behavior, and gate the surface with preparation, restart, failure-normalization, socket, documentation, and full deterministic corpora.

      11. 22a5e68d
        Problem: metadata-table reads cannot join composed workflows

        GetBucketMetadataTableConfiguration has strict preparation, decoding, and synchronous execution, but no provider-owned limited operation. Callers cannot compose the exact signed request, bounded response snapshot, admission certainty, or typed failure mapping into a larger completion-set state machine.

        Solution: colocate the bounded read with the Buckets provider

        Add the exact Low_Level sink initiator and Client.Buckets limited constructor, operation-last restart, typed Finish, and synchronous wait over one owner-driven state machine. Preserve the opaque provider status, expected-owner projection, singleton diagnostics, caller XML limits, cancellation, drain, and no-retry behavior, and gate the surface with exact preparation, restart, normalization, socket, documentation, and full deterministic corpora.

      12. 0d0dbbac
        Problem: metadata-table creation cannot join composed workflows

        Callers can prepare and synchronously execute CreateBucketMetadataTableConfiguration, but they cannot initiate, restart, or consume it from a provider-owned completion set. The replayable prepared body also obscures the mutation certainty and read-before-retry contract after possible admission.

        Solution: add one-shot provider-owned metadata-table creation

        Move the prepared payload onto the existing non-rewindable owned-source path, add exact low-level admission gating, and colocate the limited constructor, operation-last restart, typed Finish, and typed synchronous wait in Client.Buckets. Preserve signed MD5/checksum and owner projection, expose conservative mutation certainty, require read-only reconciliation for unknown outcomes, and gate ownership, bounds, restart, cross-operation rejection, and the complete certainty matrix.

      13. c457fcd8
        Problem: conditional annotation deletion cannot join composed workflows

        DeleteObjectAnnotation is limited to a synchronous low-level call, so owner-driven object workflows cannot schedule it beside other provider operations or retain typed admission certainty through terminal drain.

        Solution: colocate nonreplaying annotation deletion with objects

        Add an exact low-level initiator and provider-owned constructor, operation-last restart, typed Finish, and synchronous wait over one state machine. Copy all request identity, preserve one-shot mutation semantics, normalize publication certainty conservatively, and gate the API with exhaustive mapping and signed socket coverage.

      14. f1cd6026
        Problem: replication deletion cannot join composed workflows

        DeleteBucketReplication is available only through synchronous convenience calls, so owner-driven callers cannot retain typed admission certainty, reuse an established operation, or compose it with sibling work.

        Solution: colocate composable replication deletion with the bucket provider

        Add the exact low-level initiator and provider-owned limited operation, operation-last initiation, typed Finish, and typed synchronous wait. Drive the convenience form through the same non-replaying state machine and gate its certainty, ownership, bounds, wire behavior, and documentation exhaustively.

      15. 068b0a9a
        Problem: website deletion cannot join composed workflows

        DeleteBucketWebsite is available only through synchronous convenience calls, so owner-driven callers cannot retain typed admission certainty, reuse an established operation, or compose it with sibling work.

        Solution: colocate composable website deletion with the bucket provider

        Add the exact low-level initiator and provider-owned limited operation, operation-last initiation, typed Finish, and typed synchronous wait. Drive the convenience form through the same non-replaying state machine and gate its certainty, ownership, bounds, wire behavior, and documentation exhaustively.

      16. 7fd0ffc1
        Problem: inventory deletion cannot join composed workflows

        DeleteBucketInventoryConfiguration is available only through a blocking convenience call, so callers cannot schedule it with other owner-driven operations or retain typed publication certainty after possible admission.

        Solution: add a provider-owned composable inventory deletion

        Add the exact low-level initiator, limited constructor, operation-last restart, typed Finish and synchronous wait over one non-replaying state machine. Extend identifier-copy, certainty, response-bound, signed socket, verifier, API documentation and compatibility evidence.

      17. d71a924d
        Problem: CreateSession cannot join composed client workflows

        Directory-bucket callers must use a blocking scalar wrapper, cannot schedule the exchange beside other operations, and cannot inspect typed transport failure or admission certainty. The limited zeroizing credentials result also cannot safely live inside reusable operation storage.

        Solution: add a provider-owned composable CreateSession

        Retain the signed request, physically validated response metadata, and bounded raw response until typed Finish constructs credentials exactly once. Add same-name limited and operation-last forms, make both synchronous forms wait on the same state machine, and qualify cancellation, restart, request copying, response bounds, and malformed-response normalization.

      18. 55460971
        Problem: intelligent-tiering deletion cannot join composed workflows

        DeleteBucketIntelligentTieringConfiguration is available only through the synchronous bucket client, so callers cannot place it in a shared completion set or inspect typed admission certainty after an ambiguous mutation result.

        Solution: add provider-owned composable intelligent-tiering deletion

        Add exact low-level initiation, a non-replaying Client.Buckets operation with operation-last restart and typed Finish, and route the synchronous forms through the same state machine. Qualify copied inputs, certainty normalization, response bounds, malformed headers, documentation, and the pinned operation inventory.

      19. 4bf62837
        Problem: analytics deletion cannot join composed workflows

        DeleteBucketAnalyticsConfiguration is available only through the synchronous bucket client, so callers cannot share a completion set or retain typed certainty when deletion may have reached the service.

        Solution: add provider-owned composable analytics deletion

        Add an exact low-level initiator, a non-replaying Client.Buckets operation with copied request inputs, operation-last restart, typed Finish, and a synchronous wait over the same state machine. Extend the pinned verifier, certainty matrix, signed native/lightweight socket corpus, and maintained API documentation.

      20. d50be24c
        Problem: metrics deletion cannot join composed workflows

        DeleteBucketMetricsConfiguration is available only through the synchronous bucket client, so callers cannot share a completion set or preserve typed certainty when the mutation result is ambiguous.

        Solution: add provider-owned composable metrics deletion

        Add exact low-level initiation, a copied-input non-replaying Client.Buckets operation, operation-last restart, typed Finish, and a synchronous wait over the same state machine. Extend pinned canonical-target verification, certainty normalization, signed native/lightweight sockets, bounded-response faults, and maintained documentation.

      21. c12288e0
        Problem: metadata deletion cannot join composed workflows

        DeleteBucketMetadataConfiguration is available only through the synchronous convenience path, so owner-driven callers cannot compose it, inspect typed admission certainty, or reuse the provider operation without a parallel wrapper.

        Solution: add provider-owned composable metadata deletion

        Add the exact Low_Level initiator and Client.Buckets limited constructor, operation-last restart, typed Finish, and typed synchronous wait over one non-replaying state machine. Gate exact operation binding, copied owner input, certainty normalization, bounded physical responses, native/lightweight sockets, model inventory, and API documentation.

      22. b6552934
        Problem: metadata-table deletion cannot join composed workflows

        DeleteBucketMetadataTableConfiguration remains on the last generic blocking bucket-configuration dispatcher. Owner-driven callers cannot compose it, inspect typed admission certainty, or reuse its operation without maintaining a parallel API path.

        Solution: add provider-owned composable metadata-table deletion

        Add the exact Low_Level initiator, limited constructor, operation-last restart, typed Finish, and synchronous wait over one nonreplaying state machine. Rewrite the convenience call through it, gate exact wire and lifecycle behavior, document the provider surface, and remove the now-dead generic dispatcher.

      23. 0cd84b09
        Problem: lifecycle configuration reads remain model-only

        The pinned S3 surface can prepare the request, but callers cannot compose or strictly decode the complete lifecycle configuration graph. This leaves a common retention and cost-control read outside the provider-owned client.

        Solution: add a complete provider-owned lifecycle read

        Add the strict full-graph codec, exact low-level preparation and decoding, limited constructor, reusable initiation, typed Finish, and synchronous wait over one state machine. Gate all 36 modeled members, strict limits, headers, ownership, and native/lightweight execution, and record the client-only coverage boundary.

      24. c361be0d
        Problem: lifecycle configuration writes remain model-only

        The current PutBucketLifecycleConfiguration operation has no exact typed low-level or provider-owned composable client, leaving callers without bounded serialization, request-checksum projection, or mutation certainty.

        Solution: add the complete lifecycle configuration write client

        Serialize the pinned request graph, add explicit low-level and provider-owned one-shot APIs, and qualify model identity, limits, signing, certainty, native/lightweight sockets, documentation, and coverage.

      25. 735fb607
        Problem: Current bucket notification configuration lacks a complete composable client

        The current GetBucketNotificationConfiguration and
        PutBucketNotificationConfiguration operations remain partial in the S3 ledger.
        Callers cannot preserve the full destination and filter graph or use the
        provider-owned limited constructor, reusable initiation, typed Finish, and
        same-state-machine synchronous forms with explicit mutation certainty.

        Solution: Add strict current notification GET and PUT clients

        Add the bounded presence-preserving REST/XML codec, exact signed low-level
        preparation and execution, provider-owned GET and non-replaying PUT state
        machines, typed certainty mapping, deterministic model and socket gates, and
        documented coverage. Keep the deprecated notification operations excluded.

    2. 735fb607 updated to 5876862cindex fc0cd1dc

      1 source commit

      1. 5876862c
        Problem: GetBucketReplication lacks a complete composable client contract

        Callers can prepare only part of the operation and cannot receive the pinned
        replication graph through the provider-owned synchronous and composable state
        machine. The coverage corpus therefore cannot qualify the current modeled
        response, strict bounds, or prepared-operation admission boundary.

        Solution: add the bounded provider-owned replication read

        Add a strict presence-preserving replication XML codec, exact low-level
        preparation and decoding, and synchronous, limited-constructor, reusable, and
        typed Finish forms in Client.Buckets. Gate the complete pinned structural
        graph, signed native/lightweight sockets, normalization, bounds, and coverage,
        and document the prose-only cross-field policy boundary.

    3. 5876862c updated to 0673cdadindex eecf5c64

      1 source commit

      1. 0673cdad
        Problem: PutBucketReplication lacks a typed bounded replacement API

        Clients can read bucket replication configuration but cannot replace the same complete graph through the provider-owned composable boundary. Callers would otherwise have to assemble signing, one-shot body ownership, response bounds, and mutation certainty themselves, risking replay or an unsound definite-outcome classification.

        Solution: Add nonreplaying provider-owned replication replacement

        Serialize the reviewed presence-sensitive replication graph under caller limits, prepare and sign the exact modeled request, and expose low-level, limited-constructor, operation-last, typed Finish, and synchronous forms over one state machine. Add deterministic model/XML/certainty coverage, native and lightweight signed socket evidence, maintained documentation, and coverage bookkeeping.

    4. 0673cdad updated to aff992c0index d1470f67

      5 source commits

      1. ded98183
        Problem: Consumer agent resources lag the shared policy

        This repository is pinned to an older flyology-ada/agents revision, so its generated instructions and installed skills omit the current shared assurance workflows.

        Solution: Update the shared agents dependency

        Advance the lockfile to agents revision aa7c026, reinstall the package graph, and regenerate the Codex instructions.

      2. c268566a
        Merge pull request #1 from flyology-ada/codex/update-agents-aa7c026

        Update shared agents to aa7c026

      3. 4da54070
        Problem: The agents lock retains foundation policy in the TLA+ skill

        This consumer remains pinned to the prior shared agents revision, whose TLA+ workflow includes repository architecture constraints unrelated to using the skill.

        Solution: Update the shared agents lock

        Advance flyology-ada/agents to revision 6a97e7a and record the refined agent-focused TLA+ skill deployment hashes.

      4. 1ec12695
        Merge pull request #2 from flyology-ada/codex/update-agents-6a97e7a

        Update shared agents to 6a97e7a

      5. aff992c0
        Problem: S3 operation qualification repeats unsynchronized mechanics

        Each new S3 operation manually repeats pinned-model parsing, coverage bookkeeping, verifier registration, corpus ordering, and documentation updates. The duplicated inventories have already drifted and make completing the remaining 116-operation surface slower and easier to misclassify.

        Solution: establish a reviewed operation and evidence registry

        Add a human-owned TOML inventory for all 116 pinned operations, a shared uv-driven model/audit/scaffold/qualify tool, generated coverage counts, test registration, and documentation, plus layer-specific executable-evidence checks and negative oracles. Preserve every existing coverage state and corpus order, use GetBucketReplication as the reviewed equivalence canary, and leave legacy Ada implementations unchanged for incremental family migration.

    5. aff992c0 updated to ace67878index 77fa3822

      2 source commits

      1. 06c6331a
        Problem: Bounded REST/XML reads duplicate lifecycle mechanics

        Provider operations repeat response buffering, singleton-header validation, hidden HTTP child drain, cancellation, restart cleanup, and typed terminal storage. This slows operation coverage and lets semantically equivalent read paths drift.

        Solution: Share the owner-driven bounded REST/XML read family

        Add an implementation generic for invariant transport and ownership mechanics, then migrate GetBucketReplication as the retrospective canary. Keep provider-owned public signatures, request preparation, decoding, classification, and synchronous-over-composable behavior unchanged, and record executable shared-family provenance in the operation registry.

      2. ace67878
        Problem: Hosted tests cannot run the uv operation verifier

        The root test gate invokes the generated S3 operation registry checks through uv, but the hosted test jobs do not install uv. Both Linux and macOS therefore fail after a successful Ada build, leaving the automation foundation unqualified.

        Solution: Install and enforce the reviewed uv toolchain in CI

        Install exact uv 0.11.28 through immutable setup-uv v9.0.0 in the integrity and test jobs. Extend workflow policy and its negative oracle so both the action and tool version remain pinned.

    6. ace67878 updated to f1a2a7b7index b8287ca4

      1 source commit

      1. f1a2a7b7
        Problem: Signed S3 qualification repeats model-owned mechanics

        Each bounded REST/XML operation manually duplicates exact HTTP targets, signed headers, malformed XML fixtures, socket sequencing, and test registration. Those copies can drift from the pinned Botocore model and make each operation expensive to qualify.

        Solution: Generate data-driven qualification from reviewed decisions

        Derive signed request plans and routine negative XML cases from the pinned model, run them through a shared uv loopback driver and small typed Ada adapter, and register executable evidence from the operation manifest. GetBucketReplication is the retrospective 23-case equivalence canary, while the prospective metrics query oracle verifies reusable canonical query generation.

    7. f1a2a7b7 updated to f65afbf2index a6c27440

      1 source commit

      1. f65afbf2
        Problem: New bounded S3 reads still repeat qualification mechanics

        The shared bounded REST/XML state machine and operation registry establish reusable transport and model evidence, but the first new operation must prove that reviewed API decisions, generated negative XML, signed requests, coverage registration, and documentation can advance without restoring per-operation shell bookkeeping. GetBucketMetricsConfiguration remains partial and invisible to callers until that path is exercised end to end.

        Solution: qualify GetBucketMetricsConfiguration through the shared family

        Add the strict presence-preserving metrics codec and provider-owned low-level, composable, restart, Finish, and synchronous forms over the shared state machine. Record only reviewed semantics and fixtures in the registry, derive the model-owned request and 17 malformed XML cases, run them through a small typed socket adapter, and make the independent coverage oracle discover test trees instead of a maintained filename list. Preserve explicit caller limits and the model's lack of an inferred filter-cardinality or identifier-content constraint.

    8. f65afbf2 updated to 4e5af762index 51207f33

      1 source commit

      1. 4e5af762
        Problem: named analytics reads lack composable coverage

        GetBucketAnalyticsConfiguration is tracked by the pinned S3 model but has no
        typed provider API or executable client evidence. Callers cannot perform one
        bounded named analytics read through the shared owner-driven state machine,
        and the operation registry therefore retains partial client coverage.

        Solution: qualify analytics reads through the shared REST/XML family

        Add a strict model-aligned analytics codec, exact low-level preparation and
        decoding, and provider-owned limited, restartable, typed Finish, and
        synchronous forms. Register reviewed signed cases and model-derived negative
        XML evidence, regenerate the coverage artifacts, and document the resulting
        client-only compatibility boundary.

    9. 4e5af762 updated to 7cbcb44eindex 826970c6

      1 source commit

      1. 7cbcb44e
        Problem: named Intelligent-Tiering reads lack composable coverage

        GetBucketIntelligentTieringConfiguration is tracked by the pinned S3 model
        but has no typed provider API or executable client evidence. Callers cannot
        perform a bounded named configuration read through the shared owner-driven
        state machine, and registry coverage remains partial.

        Solution: qualify Intelligent-Tiering reads through the shared REST/XML family

        Add a strict model-aligned codec, exact low-level preparation and decoding,
        and provider-owned limited, restartable, typed Finish, and synchronous forms.
        Register reviewed signed cases and model-derived negatives, regenerate
        coverage artifacts, and document client-only compatibility.

    10. 7cbcb44e updated to 9fb63d01index 2fe4325e

      1 source commit

      1. 9fb63d01
        Problem: GetBucketInventoryConfiguration lacks a qualified client surface

        Callers cannot read named S3 inventory configurations through the provider-
        centric synchronous and composable APIs. The coverage registry therefore keeps
        the operation partial even though it belongs to the established bounded
        REST/XML read family.

        Solution: add the typed inventory read through the shared family

        Add the strict complete inventory codec, exact low-level preparation and
        decoding, provider-owned constructor/restart/Finish/synchronous forms, and
        model-derived negative and signed-socket qualification. Record the reviewed
        model decisions and executable evidence without claiming backend, server, or
        external-provider support.

    11. 9fb63d01 updated to 10d46346index 400ea643

      1 source commit

      1. 10d46346
        Problem: GetBucketLogging remains outside the qualified shared read family

        The current development line leaves bucket logging as a partial generated client with no provider-owned composable operation or executable corpus. Its modeled payload also uses a wire-root alias, a nonflattened grant list, and required namespaced attributes that the operation verifier cannot yet qualify without manual negative-case work.

        Solution: Add the strict logging client and extend model-driven qualification

        Add the provider-centric low-level, composable, and synchronous Get_Logging forms over the shared bounded REST/XML read state machine. Decode the complete presence-preserving logging graph, disabled state, exact grantee attributes and enum domains, and modeled errors without adding defaults or replay policy. Extend the uv tool to verify structurally equivalent payload aliases, namespaced attributes, and nonflattened list members, then generate and execute the signed and negative XML evidence and update the coverage and architecture records.

    12. 10d46346 updated to f5618821index d2404a6d

      1 source commit

      1. f5618821
        Problem: GetBucketWebsite remains outside the qualified shared read family

        The public client and signed corpus leave bucket website configuration unreadable, and the model verifier rejects the operation's documented payload alias even though its wire structure matches the reviewed WebsiteConfiguration shape. Repeating another handwritten bounded REST/XML read would also preserve the rollout bottleneck.

        Solution: Add a strict provider-owned website read and model-driven evidence

        Add the presence-preserving Website configuration codec, low-level and provider-owned composable/synchronous calls, generated negative XML and signed-socket qualification, and registry coverage. Verify payload aliases structurally while ignoring documentation-only differences and retaining all wire traits, so the shared bounded read family can qualify the operation without semantic drift.

    13. f5618821 updated to d0fd10d7index fdc77edc

      1 source commit

      1. d0fd10d7
        Problem: Paginated configuration reads repeat an unqualified XML envelope

        The remaining bucket-configuration list operations share strict REST/XML page mechanics, request continuation projection, bounded response ownership, and signed qualification structure. Reimplementing those mechanics operation by operation slows coverage work and risks semantic or evidence drift.

        Solution: Add a shared strict page family and qualify Metrics as its canary

        Add a private paginated REST/XML envelope generic, reuse the reviewed metrics item codec, and expose provider-owned one-page synchronous and composable ListBucketMetricsConfigurations calls over the existing bounded read state machine. Record reviewed manifest decisions and generate the model-derived negative XML, signed socket, coverage, registration, and documentation evidence, while keeping continuation caller-driven and public policy unchanged.

    14. d0fd10d7 updated to f28a3fb6index b79170c4

      1 source commit

      1. f28a3fb6
        Problem: Analytics configuration pages remain outside the shared read family

        ListBucketAnalyticsConfigurations is still represented only by model inventory, so callers lack a qualified one-page provider API and each future implementation risks repeating page-envelope, ownership, and evidence mechanics.

        Solution: Qualify Analytics through the paginated REST/XML family

        Reuse the reviewed analytics item decoder inside the shared strict page envelope, add exact low-level and provider-owned synchronous/composable calls over the existing bounded state machine, and generate the model-derived negative, signed-socket, coverage, registration, and documentation evidence from reviewed manifest decisions.

    Compare source revisions
    Development update

    flyology_object_storage_sqlite 0.1.0-dev

    14 updates: 6ec20483 through f28a3fb6

    SQLite catalog backend for Flyology Object Storage

    Manifest fields
    origin
    Show all 14 updates
    1. 6ec20483 updated to 735fb607index a47fabdb

      25 source commits

      1. 94c0ee9c
        Problem: DeleteBucketLifecycle cannot join composed client workflows

        The exact lifecycle deletion remains limited to blocking convenience and prepared execution. Callers cannot own it in a completion set, preserve typed admission certainty, or reuse its state without a parallel wrapper.

        Solution: add the provider-owned lifecycle deletion operation

        Add the exact low-level initiator and colocated Client.Buckets constructor, operation-last initiation, typed Finish, and synchronous wait over one non-replaying state machine. Gate certainty, prepared-operation identity, physical headers, response bounds, restart, native/lightweight execution, and document the provider inventory.

      2. 571522b3
        Problem: GetBucketPolicyStatus cannot join owner-driven client workflows

        The existing convenience client executes synchronously through its own path, so callers cannot compose the exact signed policy-status read with other provider operations or reuse its operation state safely.

        Solution: colocate a bounded composable policy-status operation

        Add the exact low-level initiator, provider-owned limited constructor, operation-last restart, typed Finish, and typed synchronous wait. Drive the convenience overload through the same bounded state machine, reject malformed singleton headers and over-limit bodies, and qualify the result mapping and native/lightweight socket behavior.

      3. 1c0455b9
        Problem: GetBucketRequestPayment cannot join owner-driven client workflows

        Requester-payment reads are available only through the blocking executor, so structured callers cannot own their deadline, cancellation, operation reuse, typed HTTP outcome, and bounded response lifecycle alongside other work.

        Solution: Colocate a bounded composable requester-payment read

        Add exact prepared-request admission, provider-owned limited construction and operation-last restart, typed Finish and synchronous wait, strict header and response bounds, full normalization and loopback corpora, and maintained API documentation. The established convenience call now waits on the same state machine without adding retry or billing-policy interpretation.

      4. 6befc49a
        Problem: PutBucketRequestPayment cannot join composed client workflows

        The synchronous requester-payment mutation owns no reusable operation, exposes no admission certainty, and cannot participate in a caller-owned completion set.

        Solution: add a non-replaying provider-owned requester-payment operation

        Add the exact low-level initiator, limited constructor, operation-last restart, typed Finish and synchronous wait over one state machine. Own the signed payer bytes through terminal drain, preserve strict response bounds and headers, classify ambiguous outcomes without replay, and gate the contract with certainty, socket, model, documentation and repository checks.

      5. 4664482f
        Problem: PutBucketAbac cannot join composed client workflows

        Callers can only execute PutBucketAbac synchronously, so owner-driven state machines cannot retain typed publication certainty or reconcile ambiguous outcomes without a parallel adapter.

        Solution: add a provider-owned non-replaying ABAC operation

        Expose exact low-level initiation and Client.Buckets limited-constructor, operation-last, typed Finish, and synchronous-wait forms over one state machine. Preserve the serialized status as a one-shot owned source, normalize admission certainty, extend exact-operation and socket corpora, and document the provider inventory and reconciliation contract.

      6. cc04da27
        Problem: PutBucketAccelerateConfiguration cannot compose

        Callers can only execute the acceleration mutation synchronously, so owner-driven workflows cannot preserve typed admission certainty or reconcile ambiguous publication without a separate adapter.

        Solution: add the provider-owned acceleration operation

        Expose the exact one-shot low-level initiator and Client.Buckets limited-constructor, operation-last, typed Finish, and synchronous-wait forms over one state machine. Preserve the model's no-Content-MD5 rule, normalize mutation certainty, extend exact-operation and socket corpora, and document read reconciliation and the updated provider inventory.

      7. 062f8119
        Problem: GetBucketAbac cannot join reconciliation workflows

        Callers can read the optional ABAC state only through a blocking convenience call, so a possibly admitted PutBucketAbac cannot compose its read-only reconciliation with other owner-driven operations. The low-level prepared-request boundary also has no exact reusable initiator for this operation.

        Solution: add one provider-owned bounded GetBucketAbac state machine

        Add the exact Low_Level initiator, limited constructor, operation-last reusable form, typed Finish, and typed synchronous wait in Client.Buckets. Drive the convenience call through that same state machine, preserve the caller-selected XML bound and inherited defaults, and qualify exact operation binding, restart, response normalization, singleton headers, limits, documentation, and ownership without adding retry or helper tasks.

      8. 59ea351b
        Problem: acceleration reads cannot join reconciliation workflows

        Callers that need to reconcile PutBucketAccelerateConfiguration outcomes can only use the blocking convenience read. The exact prepared request has no reusable initiator, so owner-driven workflows cannot compose the bounded response without introducing a parallel state machine.

        Solution: colocate a bounded acceleration read with the Buckets provider

        Add the exact Low_Level initiator, limited constructor, operation-last restart, typed Finish, and typed synchronous wait. Drive the existing convenience overload through the same provider-owned state machine, enforce caller-selected response bounds and singleton headers, and qualify request binding, restart, normalization, malformed headers, and overflow without retries or helper tasks.

      9. 45564e81
        Problem: bucket ACL reads cannot join composed workflows

        GetBucketAcl has a strict typed low-level synchronous client and an authenticated server route, but no provider-owned limited operation. Callers cannot coordinate ACL reads with completion-set workflows without introducing a parallel execution path.

        Solution: colocate a bounded ACL read with the Buckets provider

        Add the exact Low_Level initiator, limited constructor, operation-last restart, typed Finish, and typed synchronous wait. Retain the signed request and bounded response through terminal drain, preserve physical singleton headers and admission diagnostics, and qualify exact binding, restart, normalization, and response limits without retries or helper tasks.

      10. 6b4e9836
        Problem: object ACL reads cannot join composed workflows

        GetObjectAcl has a strict typed synchronous client and authenticated server route, but it lacks the provider-owned limited operation needed by caller-driven completion sets. Callers otherwise need a second API shape and cannot reuse the exact signed request, bounded response, admission certainty, or failure mapping in a larger state machine.

        Solution: colocate a bounded ACL read with the Objects provider

        Add the exact Low_Level sink initiator and Client.Objects limited constructor, operation-last restart, typed Finish, and synchronous wait over one owner-driven state machine. Preserve exact version, requester-pays, expected-owner, singleton-header, caller-limit, cancellation, drain, and no-retry behavior, and gate the surface with preparation, restart, failure-normalization, socket, documentation, and full deterministic corpora.

      11. 22a5e68d
        Problem: metadata-table reads cannot join composed workflows

        GetBucketMetadataTableConfiguration has strict preparation, decoding, and synchronous execution, but no provider-owned limited operation. Callers cannot compose the exact signed request, bounded response snapshot, admission certainty, or typed failure mapping into a larger completion-set state machine.

        Solution: colocate the bounded read with the Buckets provider

        Add the exact Low_Level sink initiator and Client.Buckets limited constructor, operation-last restart, typed Finish, and synchronous wait over one owner-driven state machine. Preserve the opaque provider status, expected-owner projection, singleton diagnostics, caller XML limits, cancellation, drain, and no-retry behavior, and gate the surface with exact preparation, restart, normalization, socket, documentation, and full deterministic corpora.

      12. 0d0dbbac
        Problem: metadata-table creation cannot join composed workflows

        Callers can prepare and synchronously execute CreateBucketMetadataTableConfiguration, but they cannot initiate, restart, or consume it from a provider-owned completion set. The replayable prepared body also obscures the mutation certainty and read-before-retry contract after possible admission.

        Solution: add one-shot provider-owned metadata-table creation

        Move the prepared payload onto the existing non-rewindable owned-source path, add exact low-level admission gating, and colocate the limited constructor, operation-last restart, typed Finish, and typed synchronous wait in Client.Buckets. Preserve signed MD5/checksum and owner projection, expose conservative mutation certainty, require read-only reconciliation for unknown outcomes, and gate ownership, bounds, restart, cross-operation rejection, and the complete certainty matrix.

      13. c457fcd8
        Problem: conditional annotation deletion cannot join composed workflows

        DeleteObjectAnnotation is limited to a synchronous low-level call, so owner-driven object workflows cannot schedule it beside other provider operations or retain typed admission certainty through terminal drain.

        Solution: colocate nonreplaying annotation deletion with objects

        Add an exact low-level initiator and provider-owned constructor, operation-last restart, typed Finish, and synchronous wait over one state machine. Copy all request identity, preserve one-shot mutation semantics, normalize publication certainty conservatively, and gate the API with exhaustive mapping and signed socket coverage.

      14. f1cd6026
        Problem: replication deletion cannot join composed workflows

        DeleteBucketReplication is available only through synchronous convenience calls, so owner-driven callers cannot retain typed admission certainty, reuse an established operation, or compose it with sibling work.

        Solution: colocate composable replication deletion with the bucket provider

        Add the exact low-level initiator and provider-owned limited operation, operation-last initiation, typed Finish, and typed synchronous wait. Drive the convenience form through the same non-replaying state machine and gate its certainty, ownership, bounds, wire behavior, and documentation exhaustively.

      15. 068b0a9a
        Problem: website deletion cannot join composed workflows

        DeleteBucketWebsite is available only through synchronous convenience calls, so owner-driven callers cannot retain typed admission certainty, reuse an established operation, or compose it with sibling work.

        Solution: colocate composable website deletion with the bucket provider

        Add the exact low-level initiator and provider-owned limited operation, operation-last initiation, typed Finish, and typed synchronous wait. Drive the convenience form through the same non-replaying state machine and gate its certainty, ownership, bounds, wire behavior, and documentation exhaustively.

      16. 7fd0ffc1
        Problem: inventory deletion cannot join composed workflows

        DeleteBucketInventoryConfiguration is available only through a blocking convenience call, so callers cannot schedule it with other owner-driven operations or retain typed publication certainty after possible admission.

        Solution: add a provider-owned composable inventory deletion

        Add the exact low-level initiator, limited constructor, operation-last restart, typed Finish and synchronous wait over one non-replaying state machine. Extend identifier-copy, certainty, response-bound, signed socket, verifier, API documentation and compatibility evidence.

      17. d71a924d
        Problem: CreateSession cannot join composed client workflows

        Directory-bucket callers must use a blocking scalar wrapper, cannot schedule the exchange beside other operations, and cannot inspect typed transport failure or admission certainty. The limited zeroizing credentials result also cannot safely live inside reusable operation storage.

        Solution: add a provider-owned composable CreateSession

        Retain the signed request, physically validated response metadata, and bounded raw response until typed Finish constructs credentials exactly once. Add same-name limited and operation-last forms, make both synchronous forms wait on the same state machine, and qualify cancellation, restart, request copying, response bounds, and malformed-response normalization.

      18. 55460971
        Problem: intelligent-tiering deletion cannot join composed workflows

        DeleteBucketIntelligentTieringConfiguration is available only through the synchronous bucket client, so callers cannot place it in a shared completion set or inspect typed admission certainty after an ambiguous mutation result.

        Solution: add provider-owned composable intelligent-tiering deletion

        Add exact low-level initiation, a non-replaying Client.Buckets operation with operation-last restart and typed Finish, and route the synchronous forms through the same state machine. Qualify copied inputs, certainty normalization, response bounds, malformed headers, documentation, and the pinned operation inventory.

      19. 4bf62837
        Problem: analytics deletion cannot join composed workflows

        DeleteBucketAnalyticsConfiguration is available only through the synchronous bucket client, so callers cannot share a completion set or retain typed certainty when deletion may have reached the service.

        Solution: add provider-owned composable analytics deletion

        Add an exact low-level initiator, a non-replaying Client.Buckets operation with copied request inputs, operation-last restart, typed Finish, and a synchronous wait over the same state machine. Extend the pinned verifier, certainty matrix, signed native/lightweight socket corpus, and maintained API documentation.

      20. d50be24c
        Problem: metrics deletion cannot join composed workflows

        DeleteBucketMetricsConfiguration is available only through the synchronous bucket client, so callers cannot share a completion set or preserve typed certainty when the mutation result is ambiguous.

        Solution: add provider-owned composable metrics deletion

        Add exact low-level initiation, a copied-input non-replaying Client.Buckets operation, operation-last restart, typed Finish, and a synchronous wait over the same state machine. Extend pinned canonical-target verification, certainty normalization, signed native/lightweight sockets, bounded-response faults, and maintained documentation.

      21. c12288e0
        Problem: metadata deletion cannot join composed workflows

        DeleteBucketMetadataConfiguration is available only through the synchronous convenience path, so owner-driven callers cannot compose it, inspect typed admission certainty, or reuse the provider operation without a parallel wrapper.

        Solution: add provider-owned composable metadata deletion

        Add the exact Low_Level initiator and Client.Buckets limited constructor, operation-last restart, typed Finish, and typed synchronous wait over one non-replaying state machine. Gate exact operation binding, copied owner input, certainty normalization, bounded physical responses, native/lightweight sockets, model inventory, and API documentation.

      22. b6552934
        Problem: metadata-table deletion cannot join composed workflows

        DeleteBucketMetadataTableConfiguration remains on the last generic blocking bucket-configuration dispatcher. Owner-driven callers cannot compose it, inspect typed admission certainty, or reuse its operation without maintaining a parallel API path.

        Solution: add provider-owned composable metadata-table deletion

        Add the exact Low_Level initiator, limited constructor, operation-last restart, typed Finish, and synchronous wait over one nonreplaying state machine. Rewrite the convenience call through it, gate exact wire and lifecycle behavior, document the provider surface, and remove the now-dead generic dispatcher.

      23. 0cd84b09
        Problem: lifecycle configuration reads remain model-only

        The pinned S3 surface can prepare the request, but callers cannot compose or strictly decode the complete lifecycle configuration graph. This leaves a common retention and cost-control read outside the provider-owned client.

        Solution: add a complete provider-owned lifecycle read

        Add the strict full-graph codec, exact low-level preparation and decoding, limited constructor, reusable initiation, typed Finish, and synchronous wait over one state machine. Gate all 36 modeled members, strict limits, headers, ownership, and native/lightweight execution, and record the client-only coverage boundary.

      24. c361be0d
        Problem: lifecycle configuration writes remain model-only

        The current PutBucketLifecycleConfiguration operation has no exact typed low-level or provider-owned composable client, leaving callers without bounded serialization, request-checksum projection, or mutation certainty.

        Solution: add the complete lifecycle configuration write client

        Serialize the pinned request graph, add explicit low-level and provider-owned one-shot APIs, and qualify model identity, limits, signing, certainty, native/lightweight sockets, documentation, and coverage.

      25. 735fb607
        Problem: Current bucket notification configuration lacks a complete composable client

        The current GetBucketNotificationConfiguration and
        PutBucketNotificationConfiguration operations remain partial in the S3 ledger.
        Callers cannot preserve the full destination and filter graph or use the
        provider-owned limited constructor, reusable initiation, typed Finish, and
        same-state-machine synchronous forms with explicit mutation certainty.

        Solution: Add strict current notification GET and PUT clients

        Add the bounded presence-preserving REST/XML codec, exact signed low-level
        preparation and execution, provider-owned GET and non-replaying PUT state
        machines, typed certainty mapping, deterministic model and socket gates, and
        documented coverage. Keep the deprecated notification operations excluded.

    2. 735fb607 updated to 5876862cindex fc0cd1dc

      1 source commit

      1. 5876862c
        Problem: GetBucketReplication lacks a complete composable client contract

        Callers can prepare only part of the operation and cannot receive the pinned
        replication graph through the provider-owned synchronous and composable state
        machine. The coverage corpus therefore cannot qualify the current modeled
        response, strict bounds, or prepared-operation admission boundary.

        Solution: add the bounded provider-owned replication read

        Add a strict presence-preserving replication XML codec, exact low-level
        preparation and decoding, and synchronous, limited-constructor, reusable, and
        typed Finish forms in Client.Buckets. Gate the complete pinned structural
        graph, signed native/lightweight sockets, normalization, bounds, and coverage,
        and document the prose-only cross-field policy boundary.

    3. 5876862c updated to 0673cdadindex eecf5c64

      1 source commit

      1. 0673cdad
        Problem: PutBucketReplication lacks a typed bounded replacement API

        Clients can read bucket replication configuration but cannot replace the same complete graph through the provider-owned composable boundary. Callers would otherwise have to assemble signing, one-shot body ownership, response bounds, and mutation certainty themselves, risking replay or an unsound definite-outcome classification.

        Solution: Add nonreplaying provider-owned replication replacement

        Serialize the reviewed presence-sensitive replication graph under caller limits, prepare and sign the exact modeled request, and expose low-level, limited-constructor, operation-last, typed Finish, and synchronous forms over one state machine. Add deterministic model/XML/certainty coverage, native and lightweight signed socket evidence, maintained documentation, and coverage bookkeeping.

    4. 0673cdad updated to aff992c0index d1470f67

      5 source commits

      1. ded98183
        Problem: Consumer agent resources lag the shared policy

        This repository is pinned to an older flyology-ada/agents revision, so its generated instructions and installed skills omit the current shared assurance workflows.

        Solution: Update the shared agents dependency

        Advance the lockfile to agents revision aa7c026, reinstall the package graph, and regenerate the Codex instructions.

      2. c268566a
        Merge pull request #1 from flyology-ada/codex/update-agents-aa7c026

        Update shared agents to aa7c026

      3. 4da54070
        Problem: The agents lock retains foundation policy in the TLA+ skill

        This consumer remains pinned to the prior shared agents revision, whose TLA+ workflow includes repository architecture constraints unrelated to using the skill.

        Solution: Update the shared agents lock

        Advance flyology-ada/agents to revision 6a97e7a and record the refined agent-focused TLA+ skill deployment hashes.

      4. 1ec12695
        Merge pull request #2 from flyology-ada/codex/update-agents-6a97e7a

        Update shared agents to 6a97e7a

      5. aff992c0
        Problem: S3 operation qualification repeats unsynchronized mechanics

        Each new S3 operation manually repeats pinned-model parsing, coverage bookkeeping, verifier registration, corpus ordering, and documentation updates. The duplicated inventories have already drifted and make completing the remaining 116-operation surface slower and easier to misclassify.

        Solution: establish a reviewed operation and evidence registry

        Add a human-owned TOML inventory for all 116 pinned operations, a shared uv-driven model/audit/scaffold/qualify tool, generated coverage counts, test registration, and documentation, plus layer-specific executable-evidence checks and negative oracles. Preserve every existing coverage state and corpus order, use GetBucketReplication as the reviewed equivalence canary, and leave legacy Ada implementations unchanged for incremental family migration.

    5. aff992c0 updated to ace67878index 77fa3822

      2 source commits

      1. 06c6331a
        Problem: Bounded REST/XML reads duplicate lifecycle mechanics

        Provider operations repeat response buffering, singleton-header validation, hidden HTTP child drain, cancellation, restart cleanup, and typed terminal storage. This slows operation coverage and lets semantically equivalent read paths drift.

        Solution: Share the owner-driven bounded REST/XML read family

        Add an implementation generic for invariant transport and ownership mechanics, then migrate GetBucketReplication as the retrospective canary. Keep provider-owned public signatures, request preparation, decoding, classification, and synchronous-over-composable behavior unchanged, and record executable shared-family provenance in the operation registry.

      2. ace67878
        Problem: Hosted tests cannot run the uv operation verifier

        The root test gate invokes the generated S3 operation registry checks through uv, but the hosted test jobs do not install uv. Both Linux and macOS therefore fail after a successful Ada build, leaving the automation foundation unqualified.

        Solution: Install and enforce the reviewed uv toolchain in CI

        Install exact uv 0.11.28 through immutable setup-uv v9.0.0 in the integrity and test jobs. Extend workflow policy and its negative oracle so both the action and tool version remain pinned.

    6. ace67878 updated to f1a2a7b7index b8287ca4

      1 source commit

      1. f1a2a7b7
        Problem: Signed S3 qualification repeats model-owned mechanics

        Each bounded REST/XML operation manually duplicates exact HTTP targets, signed headers, malformed XML fixtures, socket sequencing, and test registration. Those copies can drift from the pinned Botocore model and make each operation expensive to qualify.

        Solution: Generate data-driven qualification from reviewed decisions

        Derive signed request plans and routine negative XML cases from the pinned model, run them through a shared uv loopback driver and small typed Ada adapter, and register executable evidence from the operation manifest. GetBucketReplication is the retrospective 23-case equivalence canary, while the prospective metrics query oracle verifies reusable canonical query generation.

    7. f1a2a7b7 updated to f65afbf2index a6c27440

      1 source commit

      1. f65afbf2
        Problem: New bounded S3 reads still repeat qualification mechanics

        The shared bounded REST/XML state machine and operation registry establish reusable transport and model evidence, but the first new operation must prove that reviewed API decisions, generated negative XML, signed requests, coverage registration, and documentation can advance without restoring per-operation shell bookkeeping. GetBucketMetricsConfiguration remains partial and invisible to callers until that path is exercised end to end.

        Solution: qualify GetBucketMetricsConfiguration through the shared family

        Add the strict presence-preserving metrics codec and provider-owned low-level, composable, restart, Finish, and synchronous forms over the shared state machine. Record only reviewed semantics and fixtures in the registry, derive the model-owned request and 17 malformed XML cases, run them through a small typed socket adapter, and make the independent coverage oracle discover test trees instead of a maintained filename list. Preserve explicit caller limits and the model's lack of an inferred filter-cardinality or identifier-content constraint.

    8. f65afbf2 updated to 4e5af762index 51207f33

      1 source commit

      1. 4e5af762
        Problem: named analytics reads lack composable coverage

        GetBucketAnalyticsConfiguration is tracked by the pinned S3 model but has no
        typed provider API or executable client evidence. Callers cannot perform one
        bounded named analytics read through the shared owner-driven state machine,
        and the operation registry therefore retains partial client coverage.

        Solution: qualify analytics reads through the shared REST/XML family

        Add a strict model-aligned analytics codec, exact low-level preparation and
        decoding, and provider-owned limited, restartable, typed Finish, and
        synchronous forms. Register reviewed signed cases and model-derived negative
        XML evidence, regenerate the coverage artifacts, and document the resulting
        client-only compatibility boundary.

    9. 4e5af762 updated to 7cbcb44eindex 826970c6

      1 source commit

      1. 7cbcb44e
        Problem: named Intelligent-Tiering reads lack composable coverage

        GetBucketIntelligentTieringConfiguration is tracked by the pinned S3 model
        but has no typed provider API or executable client evidence. Callers cannot
        perform a bounded named configuration read through the shared owner-driven
        state machine, and registry coverage remains partial.

        Solution: qualify Intelligent-Tiering reads through the shared REST/XML family

        Add a strict model-aligned codec, exact low-level preparation and decoding,
        and provider-owned limited, restartable, typed Finish, and synchronous forms.
        Register reviewed signed cases and model-derived negatives, regenerate
        coverage artifacts, and document client-only compatibility.

    10. 7cbcb44e updated to 9fb63d01index 2fe4325e

      1 source commit

      1. 9fb63d01
        Problem: GetBucketInventoryConfiguration lacks a qualified client surface

        Callers cannot read named S3 inventory configurations through the provider-
        centric synchronous and composable APIs. The coverage registry therefore keeps
        the operation partial even though it belongs to the established bounded
        REST/XML read family.

        Solution: add the typed inventory read through the shared family

        Add the strict complete inventory codec, exact low-level preparation and
        decoding, provider-owned constructor/restart/Finish/synchronous forms, and
        model-derived negative and signed-socket qualification. Record the reviewed
        model decisions and executable evidence without claiming backend, server, or
        external-provider support.

    11. 9fb63d01 updated to 10d46346index 400ea643

      1 source commit

      1. 10d46346
        Problem: GetBucketLogging remains outside the qualified shared read family

        The current development line leaves bucket logging as a partial generated client with no provider-owned composable operation or executable corpus. Its modeled payload also uses a wire-root alias, a nonflattened grant list, and required namespaced attributes that the operation verifier cannot yet qualify without manual negative-case work.

        Solution: Add the strict logging client and extend model-driven qualification

        Add the provider-centric low-level, composable, and synchronous Get_Logging forms over the shared bounded REST/XML read state machine. Decode the complete presence-preserving logging graph, disabled state, exact grantee attributes and enum domains, and modeled errors without adding defaults or replay policy. Extend the uv tool to verify structurally equivalent payload aliases, namespaced attributes, and nonflattened list members, then generate and execute the signed and negative XML evidence and update the coverage and architecture records.

    12. 10d46346 updated to f5618821index d2404a6d

      1 source commit

      1. f5618821
        Problem: GetBucketWebsite remains outside the qualified shared read family

        The public client and signed corpus leave bucket website configuration unreadable, and the model verifier rejects the operation's documented payload alias even though its wire structure matches the reviewed WebsiteConfiguration shape. Repeating another handwritten bounded REST/XML read would also preserve the rollout bottleneck.

        Solution: Add a strict provider-owned website read and model-driven evidence

        Add the presence-preserving Website configuration codec, low-level and provider-owned composable/synchronous calls, generated negative XML and signed-socket qualification, and registry coverage. Verify payload aliases structurally while ignoring documentation-only differences and retaining all wire traits, so the shared bounded read family can qualify the operation without semantic drift.

    13. f5618821 updated to d0fd10d7index fdc77edc

      1 source commit

      1. d0fd10d7
        Problem: Paginated configuration reads repeat an unqualified XML envelope

        The remaining bucket-configuration list operations share strict REST/XML page mechanics, request continuation projection, bounded response ownership, and signed qualification structure. Reimplementing those mechanics operation by operation slows coverage work and risks semantic or evidence drift.

        Solution: Add a shared strict page family and qualify Metrics as its canary

        Add a private paginated REST/XML envelope generic, reuse the reviewed metrics item codec, and expose provider-owned one-page synchronous and composable ListBucketMetricsConfigurations calls over the existing bounded read state machine. Record reviewed manifest decisions and generate the model-derived negative XML, signed socket, coverage, registration, and documentation evidence, while keeping continuation caller-driven and public policy unchanged.

    14. d0fd10d7 updated to f28a3fb6index b79170c4

      1 source commit

      1. f28a3fb6
        Problem: Analytics configuration pages remain outside the shared read family

        ListBucketAnalyticsConfigurations is still represented only by model inventory, so callers lack a qualified one-page provider API and each future implementation risks repeating page-envelope, ownership, and evidence mechanics.

        Solution: Qualify Analytics through the paginated REST/XML family

        Reuse the reviewed analytics item decoder inside the shared strict page envelope, add exact low-level and provider-owned synchronous/composable calls over the existing bounded state machine, and generate the model-derived negative, signed-socket, coverage, registration, and documentation evidence from reviewed manifest decisions.

    Compare source revisions
    Development update

    flyology_tla 0.1.0-dev

    3 updates: ffc459bc through faf06c48

    TLA+ trace generation and Ada conformance replay harness

    Manifest fields
    origin
    Show all 3 updates
    1. ffc459bc updated to b03cb81dindex 7c8e721f

      1 source commit

      1. b03cb81d
        Problem: process-isolated consumers require private trace codecs

        The public trace API only accepts paths and only writes prefixes to files, while result artifacts can be encoded but not strictly decoded. Consumers embedding shared evidence in their own process envelopes must use temporary files or duplicate the versioned JSON contracts, and the schema invalid-trace verdict is not representable in Ada.

        Solution: expose strict in-memory trace and result boundaries

        Add bounded trace Parse and canonical Image operations with the file APIs delegating to them. Add strict result decoding with trace identity binding, represent every schema verdict, document the envelope workflow, and cover canonical round trips plus unknown and duplicate member rejection.

    2. b03cb81d updated to e75b8483index 3a358397

      1 source commit

      1. e75b8483
        Problem: trace provenance omits resolved model inputs

        Trace version 1 binds only one caller-supplied source digest and a configuration name. Consumers with EXTENDS closures can therefore regenerate evidence after a helper or configuration change without changing the recorded model identity. Typed generation and trace normalization also compute provenance through different paths.

        Solution: bind the resolved model closure and configuration bytes

        Add trace version 2 and an authoritative SANY-backed model identity command. Share the constrained semantic export across normalization and typed generation, retain strict trace version 1 reads, and cover deterministic closure hashing, configuration hashing, schemas, compatibility, and the actual TLC/Ada/TLAPM example.

    3. e75b8483 updated to faf06c48index ea2ae205

      1 source commit

      1. faf06c48
        Problem: Replay results lose observations after adapters exit

        The result/1 contract records the exact trace and stable failure identity, but a process holding only those artifacts cannot report the adapter outcome and state at the completed divergent comparison. Current consumers must remain able to emit and strictly parse result/1 while they migrate independently.

        Solution: Add an explicit bounded result/2 comparison contract

        Introduce a source-compatible Replay_Result_V2 API with typed initial and step observations, strict version-specific encoding and decoding, canonical embedded JSON, schema and fixtures, human reporting, and replay/CLI overloads. Keep expected values authoritative in the SHA-256-bound trace, reject impossible observation/verdict combinations, and leave adapter errors and invalid traces observation-free.

    Compare source revisions
  10. publish flyology_tla 0.1.0-dev

    a95cdc5d on GitHub
  11. Advance the indexed development origin

    dab710a4 on GitHub
  12. Development updates

    Development update

    flyology 0.1.1-dev

    2 updates: 3859f412 through bd95746d

    Experimental GNAT runtime extension for native and lightweight Ada tasks

    Manifest fields
    origin
    Show all 2 updates
    1. 3859f412 updated to ca8c23a8index 30ef277e

      3 source commits

      1. f639c4bf
        Problem: Lifecycle observers can leak retained wait capacity on abort

        Supervisor monitor registration and scoped task-result attachment can publish a retained runtime resource before their Ada controlled guards own it. Abort in that boundary can strand a monitor slot or sidecar reference, preventing later exact-generation observation and making remoting lifecycle cleanup unsafe.

        Solution: Publish lifecycle wait ownership atomically

        Move supervisor guard ownership into the protected monitor-registration cut, defer abort through task-result retain publication, and add statically elided deterministic abort barriers. The focused fixtures prove exact cleanup and capacity reuse for Static, Families, task-id waits, and retained-monitor waits while production builds contain no hook references.

      2. 954a4392
        Problem: Supervised task starts cannot remain blocked through authorization

        Remoting needs a bounded one-shot admission owner and an exact lifecycle observation that survive abort, shutdown, restart, and slot reuse. Families currently queue accepted requests immediately, while ordinary generation waits cannot retain one admission epoch across replacement publication.

        Solution: Add prepared family admissions and scoped exact observation

        Add the optional Prepared_Admissions child over existing Family slots and monitor capacity, abort-safe prepare/commit/release/cancel ownership cuts, coherent exact-epoch lifecycle observation, bounded wake publication, deterministic fault/lifetime/generation coverage, and public architecture documentation.

      3. ca8c23a8
        Merge pull request #85 from flyology-ada/codex/remoting-prepared-admissions

        Add prepared family admissions and scoped lifecycle observation

    2. ca8c23a8 updated to bd95746dindex 711715e9

      2 source commits

      1. 49960169
        Problem: Prepared admissions hide the reserved handle before commit

        Callers that must authorize, bind, or publish an exact supervised child identity while a request remains prepared cannot inspect its Child_Handle until ownership moves into Started_Admission. Remoting task admission therefore cannot validate the reserved controller, child, and generation before committing the launch.

        Solution: Expose the prepared claim's exact first handle

        Add the Start_Claim overload of First_Handle with the active-owner precondition used by Started_Admission. Document that Commit_Start transfers admission ownership while preserving the handle identity, and verify exact identity plus rollback/reprepare generation advancement.

      2. bd95746d
        Merge pull request #86 from flyology-ada/codex/prepared-admission-first-handle

        Expose prepared admission handle before commit

    Compare source revisions
    Development update

    flyology_allocators 0.1.0-dev

    2 updates: 3859f412 through bd95746d

    Caller-owned memory allocation algorithms for Ada

    Manifest fields
    origin
    Show all 2 updates
    1. 3859f412 updated to ca8c23a8index 30ef277e

      3 source commits

      1. f639c4bf
        Problem: Lifecycle observers can leak retained wait capacity on abort

        Supervisor monitor registration and scoped task-result attachment can publish a retained runtime resource before their Ada controlled guards own it. Abort in that boundary can strand a monitor slot or sidecar reference, preventing later exact-generation observation and making remoting lifecycle cleanup unsafe.

        Solution: Publish lifecycle wait ownership atomically

        Move supervisor guard ownership into the protected monitor-registration cut, defer abort through task-result retain publication, and add statically elided deterministic abort barriers. The focused fixtures prove exact cleanup and capacity reuse for Static, Families, task-id waits, and retained-monitor waits while production builds contain no hook references.

      2. 954a4392
        Problem: Supervised task starts cannot remain blocked through authorization

        Remoting needs a bounded one-shot admission owner and an exact lifecycle observation that survive abort, shutdown, restart, and slot reuse. Families currently queue accepted requests immediately, while ordinary generation waits cannot retain one admission epoch across replacement publication.

        Solution: Add prepared family admissions and scoped exact observation

        Add the optional Prepared_Admissions child over existing Family slots and monitor capacity, abort-safe prepare/commit/release/cancel ownership cuts, coherent exact-epoch lifecycle observation, bounded wake publication, deterministic fault/lifetime/generation coverage, and public architecture documentation.

      3. ca8c23a8
        Merge pull request #85 from flyology-ada/codex/remoting-prepared-admissions

        Add prepared family admissions and scoped lifecycle observation

    2. ca8c23a8 updated to bd95746dindex 711715e9

      2 source commits

      1. 49960169
        Problem: Prepared admissions hide the reserved handle before commit

        Callers that must authorize, bind, or publish an exact supervised child identity while a request remains prepared cannot inspect its Child_Handle until ownership moves into Started_Admission. Remoting task admission therefore cannot validate the reserved controller, child, and generation before committing the launch.

        Solution: Expose the prepared claim's exact first handle

        Add the Start_Claim overload of First_Handle with the active-owner precondition used by Started_Admission. Document that Commit_Start transfers admission ownership while preserving the handle identity, and verify exact identity plus rollback/reprepare generation advancement.

      2. bd95746d
        Merge pull request #86 from flyology-ada/codex/prepared-admission-first-handle

        Expose prepared admission handle before commit

    Compare source revisions
    Development update

    flyology_bench 0.1.1-dev

    2 updates: 3859f412 through bd95746d

    Adaptive nanosecond-scale benchmarking for Ada

    Manifest fields
    origin
    Show all 2 updates
    1. 3859f412 updated to ca8c23a8index 30ef277e

      3 source commits

      1. f639c4bf
        Problem: Lifecycle observers can leak retained wait capacity on abort

        Supervisor monitor registration and scoped task-result attachment can publish a retained runtime resource before their Ada controlled guards own it. Abort in that boundary can strand a monitor slot or sidecar reference, preventing later exact-generation observation and making remoting lifecycle cleanup unsafe.

        Solution: Publish lifecycle wait ownership atomically

        Move supervisor guard ownership into the protected monitor-registration cut, defer abort through task-result retain publication, and add statically elided deterministic abort barriers. The focused fixtures prove exact cleanup and capacity reuse for Static, Families, task-id waits, and retained-monitor waits while production builds contain no hook references.

      2. 954a4392
        Problem: Supervised task starts cannot remain blocked through authorization

        Remoting needs a bounded one-shot admission owner and an exact lifecycle observation that survive abort, shutdown, restart, and slot reuse. Families currently queue accepted requests immediately, while ordinary generation waits cannot retain one admission epoch across replacement publication.

        Solution: Add prepared family admissions and scoped exact observation

        Add the optional Prepared_Admissions child over existing Family slots and monitor capacity, abort-safe prepare/commit/release/cancel ownership cuts, coherent exact-epoch lifecycle observation, bounded wake publication, deterministic fault/lifetime/generation coverage, and public architecture documentation.

      3. ca8c23a8
        Merge pull request #85 from flyology-ada/codex/remoting-prepared-admissions

        Add prepared family admissions and scoped lifecycle observation

    2. ca8c23a8 updated to bd95746dindex 711715e9

      2 source commits

      1. 49960169
        Problem: Prepared admissions hide the reserved handle before commit

        Callers that must authorize, bind, or publish an exact supervised child identity while a request remains prepared cannot inspect its Child_Handle until ownership moves into Started_Admission. Remoting task admission therefore cannot validate the reserved controller, child, and generation before committing the launch.

        Solution: Expose the prepared claim's exact first handle

        Add the Start_Claim overload of First_Handle with the active-owner precondition used by Started_Admission. Document that Commit_Start transfers admission ownership while preserving the handle identity, and verify exact identity plus rollback/reprepare generation advancement.

      2. bd95746d
        Merge pull request #86 from flyology-ada/codex/prepared-admission-first-handle

        Expose prepared admission handle before commit

    Compare source revisions
    Development update

    flyology_cachelines 0.1.1-dev

    2 updates: 3859f412 through bd95746d

    Cache-line-aware storage and cache information for Ada

    Manifest fields
    origin
    Show all 2 updates
    1. 3859f412 updated to ca8c23a8index 30ef277e

      3 source commits

      1. f639c4bf
        Problem: Lifecycle observers can leak retained wait capacity on abort

        Supervisor monitor registration and scoped task-result attachment can publish a retained runtime resource before their Ada controlled guards own it. Abort in that boundary can strand a monitor slot or sidecar reference, preventing later exact-generation observation and making remoting lifecycle cleanup unsafe.

        Solution: Publish lifecycle wait ownership atomically

        Move supervisor guard ownership into the protected monitor-registration cut, defer abort through task-result retain publication, and add statically elided deterministic abort barriers. The focused fixtures prove exact cleanup and capacity reuse for Static, Families, task-id waits, and retained-monitor waits while production builds contain no hook references.

      2. 954a4392
        Problem: Supervised task starts cannot remain blocked through authorization

        Remoting needs a bounded one-shot admission owner and an exact lifecycle observation that survive abort, shutdown, restart, and slot reuse. Families currently queue accepted requests immediately, while ordinary generation waits cannot retain one admission epoch across replacement publication.

        Solution: Add prepared family admissions and scoped exact observation

        Add the optional Prepared_Admissions child over existing Family slots and monitor capacity, abort-safe prepare/commit/release/cancel ownership cuts, coherent exact-epoch lifecycle observation, bounded wake publication, deterministic fault/lifetime/generation coverage, and public architecture documentation.

      3. ca8c23a8
        Merge pull request #85 from flyology-ada/codex/remoting-prepared-admissions

        Add prepared family admissions and scoped lifecycle observation

    2. ca8c23a8 updated to bd95746dindex 711715e9

      2 source commits

      1. 49960169
        Problem: Prepared admissions hide the reserved handle before commit

        Callers that must authorize, bind, or publish an exact supervised child identity while a request remains prepared cannot inspect its Child_Handle until ownership moves into Started_Admission. Remoting task admission therefore cannot validate the reserved controller, child, and generation before committing the launch.

        Solution: Expose the prepared claim's exact first handle

        Add the Start_Claim overload of First_Handle with the active-owner precondition used by Started_Admission. Document that Commit_Start transfers admission ownership while preserving the handle identity, and verify exact identity plus rollback/reprepare generation advancement.

      2. bd95746d
        Merge pull request #86 from flyology-ada/codex/prepared-admission-first-handle

        Expose prepared admission handle before commit

    Compare source revisions
    Development update

    flyology_debug 0.1.1-dev

    2 updates: 3859f412 through bd95746d

    Bounded in-memory tracing and gauges for Ada

    Manifest fields
    origin
    Show all 2 updates
    1. 3859f412 updated to ca8c23a8index 30ef277e

      3 source commits

      1. f639c4bf
        Problem: Lifecycle observers can leak retained wait capacity on abort

        Supervisor monitor registration and scoped task-result attachment can publish a retained runtime resource before their Ada controlled guards own it. Abort in that boundary can strand a monitor slot or sidecar reference, preventing later exact-generation observation and making remoting lifecycle cleanup unsafe.

        Solution: Publish lifecycle wait ownership atomically

        Move supervisor guard ownership into the protected monitor-registration cut, defer abort through task-result retain publication, and add statically elided deterministic abort barriers. The focused fixtures prove exact cleanup and capacity reuse for Static, Families, task-id waits, and retained-monitor waits while production builds contain no hook references.

      2. 954a4392
        Problem: Supervised task starts cannot remain blocked through authorization

        Remoting needs a bounded one-shot admission owner and an exact lifecycle observation that survive abort, shutdown, restart, and slot reuse. Families currently queue accepted requests immediately, while ordinary generation waits cannot retain one admission epoch across replacement publication.

        Solution: Add prepared family admissions and scoped exact observation

        Add the optional Prepared_Admissions child over existing Family slots and monitor capacity, abort-safe prepare/commit/release/cancel ownership cuts, coherent exact-epoch lifecycle observation, bounded wake publication, deterministic fault/lifetime/generation coverage, and public architecture documentation.

      3. ca8c23a8
        Merge pull request #85 from flyology-ada/codex/remoting-prepared-admissions

        Add prepared family admissions and scoped lifecycle observation

    2. ca8c23a8 updated to bd95746dindex 711715e9

      2 source commits

      1. 49960169
        Problem: Prepared admissions hide the reserved handle before commit

        Callers that must authorize, bind, or publish an exact supervised child identity while a request remains prepared cannot inspect its Child_Handle until ownership moves into Started_Admission. Remoting task admission therefore cannot validate the reserved controller, child, and generation before committing the launch.

        Solution: Expose the prepared claim's exact first handle

        Add the Start_Claim overload of First_Handle with the active-owner precondition used by Started_Admission. Document that Commit_Start transfers admission ownership while preserving the handle identity, and verify exact identity plus rollback/reprepare generation advancement.

      2. bd95746d
        Merge pull request #86 from flyology-ada/codex/prepared-admission-first-handle

        Expose prepared admission handle before commit

    Compare source revisions
    Development update

    flyology_numa 0.1.0-dev

    2 updates: 3859f412 through bd95746d

    Memory-node topology reporting for Ada

    Manifest fields
    origin
    Show all 2 updates
    1. 3859f412 updated to ca8c23a8index 30ef277e

      3 source commits

      1. f639c4bf
        Problem: Lifecycle observers can leak retained wait capacity on abort

        Supervisor monitor registration and scoped task-result attachment can publish a retained runtime resource before their Ada controlled guards own it. Abort in that boundary can strand a monitor slot or sidecar reference, preventing later exact-generation observation and making remoting lifecycle cleanup unsafe.

        Solution: Publish lifecycle wait ownership atomically

        Move supervisor guard ownership into the protected monitor-registration cut, defer abort through task-result retain publication, and add statically elided deterministic abort barriers. The focused fixtures prove exact cleanup and capacity reuse for Static, Families, task-id waits, and retained-monitor waits while production builds contain no hook references.

      2. 954a4392
        Problem: Supervised task starts cannot remain blocked through authorization

        Remoting needs a bounded one-shot admission owner and an exact lifecycle observation that survive abort, shutdown, restart, and slot reuse. Families currently queue accepted requests immediately, while ordinary generation waits cannot retain one admission epoch across replacement publication.

        Solution: Add prepared family admissions and scoped exact observation

        Add the optional Prepared_Admissions child over existing Family slots and monitor capacity, abort-safe prepare/commit/release/cancel ownership cuts, coherent exact-epoch lifecycle observation, bounded wake publication, deterministic fault/lifetime/generation coverage, and public architecture documentation.

      3. ca8c23a8
        Merge pull request #85 from flyology-ada/codex/remoting-prepared-admissions

        Add prepared family admissions and scoped lifecycle observation

    2. ca8c23a8 updated to bd95746dindex 711715e9

      2 source commits

      1. 49960169
        Problem: Prepared admissions hide the reserved handle before commit

        Callers that must authorize, bind, or publish an exact supervised child identity while a request remains prepared cannot inspect its Child_Handle until ownership moves into Started_Admission. Remoting task admission therefore cannot validate the reserved controller, child, and generation before committing the launch.

        Solution: Expose the prepared claim's exact first handle

        Add the Start_Claim overload of First_Handle with the active-owner precondition used by Started_Admission. Document that Commit_Start transfers admission ownership while preserving the handle identity, and verify exact identity plus rollback/reprepare generation advancement.

      2. bd95746d
        Merge pull request #86 from flyology-ada/codex/prepared-admission-first-handle

        Expose prepared admission handle before commit

    Compare source revisions
    Development update

    flyology_object_storage 0.1.0-dev

    8 updates: 0761f9e2 through 6ec20483

    S3 client and pluggable object-storage server for Flyology

    Manifest fields
    origin
    Show all 8 updates
    1. 0761f9e2 updated to aa799686index 16142be3

      1 source commit

      1. aa799686
        Problem: clean hosted checkouts cannot complete the publication gates

        Strict Linux C compilation hides kill without an explicit POSIX feature contract, the proof project cannot locate an indirect Flyology project in Alire's shared cache, and shallow test checkouts cannot validate retained benchmark ancestry. The first public main CI therefore fails despite the locally qualified implementation.

        Solution: make clean-checkout requirements explicit

        Expose the POSIX.1-2008 declaration set locally in the durability bridge, prepend Alire's exported Flyology root only for maintained proof invocations, and fetch complete history for the test job that validates retained provenance.

    2. aa799686 updated to 98383e48index dee928e8

      1 source commit

      1. 98383e48
        Problem: clean hosted qualification depends on unused and fragile build paths

        Linux SQLite consumers inherit an unnecessary libm link from the optional FTS5 module, while the proof gate imports Flyology through a transitive cache location that Alire does not expose consistently in clean hosted workspaces. This prevents the published development line from completing its maintained SQLite and SPARK gates.

        Solution: narrow SQLite features and import the direct proof closure

        Disable the unused FTS5 extension instead of adding a compensating linker dependency. Make the proof project import the direct HTTP and XML project dependencies, and let the maintained script invoke GNATprove directly without reconstructing a transitive cache path.

    3. 98383e48 updated to 3455cde3index 8e99188e

      1 source commit

      1. 3455cde3
        Problem: proof-only checkouts resolve dependencies before materialization

        A clean hosted proof job invokes Alire execution before dependency build roots and generated configuration exist. The resulting GPR search path names directories that have not been synchronized, so GNATprove cannot load the direct HTTP and XML project closure.

        Solution: materialize the proof dependency closure before analysis

        Run Alire through the pre-build stage before GNATprove. This synchronizes dependencies and runs configuration actions without compiling the Object Storage library; GNATprove remains the analyzer for the selected proof units.

    4. 3455cde3 updated to 1978275bindex 27baef81

      5 source commits

      1. 09e6eac2
        Problem: DeleteBucket cannot compose with owner-driven callers

        The bucket lifecycle client exposes deletion only through blocking execution, so callers cannot share a Completion_Set and HTTP owner while retaining typed admission certainty across a possibly admitted mutation.

        Solution: Add one provider-owned non-replaying DeleteBucket operation

        Add the limited constructor, operation-last reusable initiation, typed Finish, and synchronous wait on one state machine. Use a non-rewindable empty source, bounded response retention, conservative deletion certainty, signed socket and normalization corpora, and maintainer documentation.

      2. 22fec71c
        Problem: GetBucketLocation cannot compose with owner-driven callers

        The bucket provider exposes only blocking location discovery even though callers need the raw bounded response while coordinating related operations in one Completion_Set. They must either block outside their state machine or bypass the provider-owned certainty, cancellation, and response-decoding contract.

        Solution: add one provider-owned bounded location read

        Add limited-root and operation-last Get_Location forms, a typed Finish result, and the matching prepared low-level initiator. Make the typed synchronous and legacy convenience overloads wait on the same bounded owner-driven state machine, preserve established defaults and legacy region normalization, retain no borrowed request input after signing, and leave safe GET recovery to Flyology HTTP. Gate exact response/failure normalization, expected-owner signing, fragmented XML, restart, documentation, full deterministic tests, and the warning-strict 936-check proof campaign.

      3. c0bae328
        Problem: GetBucketVersioning cannot compose with owner-driven callers

        Bucket-version reconciliation is available only through a blocking call, so structured callers cannot share a completion set, deadline, cancellation owner, or reusable operation while preserving the modeled response and HTTP failure evidence.

        Solution: add one provider-owned bounded versioning read

        Add limited-root and operation-last Get_Versioning forms with typed Finish in Client.Buckets, drive the prepared request through the shared HTTP state machine, retain XML under the versioning codec bound, preserve the established synchronous behavior, and qualify normalization, restart, documentation, and signed socket behavior.

      4. 39f97288
        Problem: PutBucketVersioning cannot compose without replay ambiguity

        Bucket-version updates are available only through blocking execution, so structured callers cannot own deadline, cancellation, and restart state or retain typed admission certainty for reconciliation.

        Solution: add one provider-owned nonreplaying versioning mutation

        Add limited-root and operation-last Set_Versioning_Configuration with typed Finish, move synchronous execution onto the same owned one-shot source, preserve exact certainty mapping, and qualify normalization, restart, documentation, signed sockets, and proof.

      5. 1978275b
        Problem: GetBucketPolicy cannot compose with owner-driven callers

        Bucket-policy retrieval is available only through blocking execution, so structured callers cannot retain typed HTTP state, caller-selected response bounds, cancellation, and restart ownership in a larger operation graph.

        Solution: add one provider-owned bounded policy read

        Add limited-root and operation-last Get_Policy with typed Finish, route the synchronous parameter-record overload through the same state machine, enforce exact prepared-operation identity, and qualify normalization, bounds, restart, documentation, signed sockets, and proof.

    5. 1978275b updated to 179b16c4index ade6ebbd

      9 source commits

      1. 0da1b4f7
        Problem: bucket policy mutations cannot join caller-owned operation graphs

        Callers can read bucket policies compositionally, but replacement and deletion still use separate blocking transport paths. That prevents provider-centric operation reuse, obscures admission certainty after ambiguous mutations, and leaves a socket-corpus startup failure able to strand clients before the server publishes its port.

        Solution: add provider-owned nonreplaying policy mutations

        Add limited Set_Policy and Delete_Policy roots, operation-last reusable initiation, typed Finish/results, exact low-level prepared-operation binding, and synchronous waits over the same one-shot state machines. Preserve owned payloads, caller-selected bounds, admission certainty, and read-only reconciliation rules; extend the signed corpus and make pre-publication server failure wake waiting clients deterministically.

      2. 5503d9d0
        Problem: Files benchmark durability provenance contradicts runtime policy

        The implementation manifest labels the Flyology files lane as not power durable even though its server uses the production durability policy. Campaign metadata also leaves that selected policy implicit, allowing later comparisons to overstate or misclassify durability equivalence.

        Solution: Pin and retain the production durability selection

        Label the matrix lane power-loss-durable, pass Power_Loss_Durable explicitly to the files server, record the exact commit policy in both retained matrix metadata streams, and gate the metadata field. Clarify the guide while leaving immutable historical evidence unchanged.

      3. 3453828c
        Problem: Public access controls cannot join composed client workflows

        PutPublicAccessBlock, GetPublicAccessBlock, and DeletePublicAccessBlock are available through synchronous helpers but not through the provider-owned operation model. Callers cannot compose these security controls with their completion sets, and mutation failures lack the typed certainty needed to choose read-only reconciliation without replay.

        Solution: Add provider-owned public access block operations

        Add limited constructors, operation-last restart procedures, typed Finish results, and synchronous waits on the same Client.Buckets state machines. Keep mutation bodies non-rewindable, preserve admission certainty and bounded same-response reads, reject mismatched prepared operations before HTTP admission, and cover lifecycle, restart, certainty, and documentation contracts.

      4. 551d514d
        Problem: Ownership controls reads cannot join composed client workflows

        Callers can retrieve bucket ownership controls only through the blocking low-level executor, so owner-driven operation graphs cannot compose the read, preserve typed HTTP failure context, or reuse an established parent operation.

        Solution: colocate bounded Ownership Controls reads with the Buckets provider

        Add limited and operation-last provider forms, typed Finish and synchronous waiting over the same state machine, an exact prepared-request initiator, bounded same-response decoding, restart and operation-identity tests, and matching architecture and compatibility evidence.

      5. 07269323
        Problem: Ownership controls writes cannot join composed client workflows

        PutBucketOwnershipControls is available only through a blocking executor, so owner-driven callers cannot retain typed admission certainty or reconcile ambiguous publication without leaving the provider API.

        Solution: add a non-replaying Ownership Controls mutation state machine

        Colocate limited, operation-last, Finish, and synchronous forms in Client.Buckets; expose an exact low-level initiator; retain serialized bytes through terminal drain; classify only response-observed exact rejections as definitely not applied; and gate operation identity, restart, wire behavior, and the complete admission-certainty matrix.

      6. 33b28a12
        Problem: Ownership controls deletion cannot join composed workflows

        DeleteBucketOwnershipControls still uses the generic blocking configuration path, so composed callers cannot retain typed admission certainty, reuse an established operation, or reconcile an ambiguous deletion through the owning provider.

        Solution: complete the provider-owned Ownership Controls trio

        Add a non-replaying Delete operation with limited and operation-last forms, typed Finish and synchronous waiting; rewrite the existing convenience call through that state machine; expose exact low-level initiation; and gate operation identity, restart, wire behavior, and exhaustive certainty normalization.

      7. da5c057f
        Problem: Bucket encryption reads cannot join composed workflows

        GetBucketEncryption is available only through the blocking executor, so owner-driven callers cannot compose its bounded response, cancellation, and deadline into an existing completion graph.

        Solution: Add a provider-owned Get_Encryption operation

        Add the exact low-level prepared initiator, limited and reusable provider overloads, typed Finish and synchronous wait over one bounded state machine. Cover exact-operation rejection, restart, response normalization, certainty, signed socket behavior, and document the expanded provider surface.

      8. e00ca596
        Problem: Bucket encryption deletion cannot join composed workflows

        DeleteBucketEncryption uses the blocking configuration dispatcher, so owner-driven callers cannot compose its one-shot mutation, deadline, cancellation, and admission certainty into an existing completion graph.

        Solution: Add a provider-owned Delete_Encryption operation

        Add the exact low-level initiator, limited and reusable provider overloads, typed Finish, and synchronous waits over one non-replaying state machine. Preserve the legacy Delete_Outcome surface through that same engine, remove its dead blocking branch, and cover exact binding, restart, certainty, response classes, and signed socket behavior.

      9. 179b16c4
        Problem: HTTP dependency oracles retain the pre-hook-selection origin

        The five no-pin solve roots now select the published HTTP/QUIC 0.1.3-dev source that removes hook preprocessing, while CI and maintained prose still assert the previous flattened-client origin.

        Solution: Advance the tracked HTTP origin qualification

        Update CI and maintainer documentation to exact eb09a80, retain exact current-dev constraints and no external pins, and align nearby composable terminology with the provider-centric API.

    6. 179b16c4 updated to 4401e0ecindex 4f7124b2

      8 source commits

      1. db16a412
        Problem: PutBucketCors cannot join composed client workflows

        The existing CORS client can read and delete configurations, but callers cannot publish a complete configuration through the provider-owned operation model. They cannot retain typed admission certainty, restart an established component, or prove that the exact modeled request graph is covered without falling back to a separate blocking path.

        Solution: add one provider-owned nonreplaying CORS mutation

        Serialize the pinned flattened CORS graph within caller-selected XML limits, prepare and execute one-shot signed requests, and colocate limited, operation-last, typed Finish, and synchronous Set_CORS forms in Client.Buckets. Add reciprocal model ledgers, deterministic and signed socket corpora, certainty normalization, coverage accounting, GNATdoc, and maintainer qualification evidence.

      2. df9d0d49
        Problem: CORS reads and deletions cannot join composed workflows

        GetBucketCors and DeleteBucketCors stop at synchronous execution even though their provider already owns exact prepared requests and bounded response decoding. Callers cannot reuse them inside completion-set state machines, and synchronous deletion does not share typed admission certainty with the composable client vocabulary.

        Solution: colocate composable CORS reads and deletions with Client.Buckets

        Add exact low-level initiators and provider-owned limited constructors, operation-last reusable procedures, typed Finish results, and synchronous waits on the same state machines. Preserve bounded decoding, non-replaying empty deletion bodies, admission certainty, and conservative outcome mapping, with signed socket, restart, mismatch, capacity, documentation, and normalization coverage.

      3. b30f0812
        Problem: Object Legal Hold cannot join composed client workflows

        GetObjectLegalHold and PutObjectLegalHold stop at blocking low-level execution, forcing callers to leave provider-owned completion sets and obscuring mutation admission certainty.

        Solution: colocate owner-driven Legal Hold operations in Client.Objects

        Add exact prepared-request initiators, limited constructors, operation-last restart, typed Finish, shared synchronous waits, an owned nonreplayable mutation source, bounded response sinks, certainty normalization, signed socket and negative corpora, and maintainer documentation.

      4. 1160fd60
        Problem: Object Retention cannot join composed client workflows

        GetObjectRetention and PutObjectRetention are available only through blocking client entry points, so completion-set state machines cannot compose exact-version retention reads or mutations without inventing a parallel wrapper. That obscures provider ownership and prevents typed admission certainty from flowing through caller-owned scheduling.

        Solution: colocate Retention operations with Client.Objects

        Add exact prepared-request initiators plus provider-owned limited constructors, operation-last reusable initiation, typed Finish, and synchronous waits driven by the same bounded state machines. Own the Put XML in a non-rewindable source, preserve conservative post-admission mutation certainty, require generation-bound read reconciliation, and gate restart, exact operation binding, normalization, and one-past response limits under native and lightweight owners.

      5. aa0a3693
        Problem: Object Lock configuration cannot join composed client workflows

        GetObjectLockConfiguration and PutObjectLockConfiguration expose only blocking execution, so completion-set state machines cannot own their lifetime, drain, certainty, and bounded response handling through the bucket provider.

        Solution: colocate owner-driven Object Lock configuration operations in Client.Buckets

        Add exact Low_Level prepared-request initiators, limited constructors, operation-last reusable procedures, typed Finish results, and synchronous waits over the same state machines. Preserve bounded same-response reads, one-shot non-replaying mutation ownership, conservative admission certainty, and read-only reconciliation, with strict socket, certainty, documentation, and API gates.

      6. d1dee5be
        Problem: PutBucketEncryption cannot join composed client workflows

        Callers can prepare and execute bucket-encryption updates synchronously, but they cannot schedule the mutation beside other owner-driven operations without rebuilding its signing, body-lifetime, and publication-certainty rules.

        Solution: add one nonreplaying provider-owned encryption mutation

        Serialize the pinned presence-sensitive configuration into caller-bounded XML, retain its exact signed bytes in the parent operation, expose limited and operation-last Set_Encryption forms with typed Finish, and make the synchronous form wait on that same state machine. Add reciprocal model inventories, deterministic and signed-socket corpora, certainty normalization coverage, qualification evidence, and honest client-only compatibility claims.

      7. 0956dcd3
        Problem: completed composable controls remain split from main

        The reviewed CORS, Object Lock configuration, Legal Hold, and Retention operation families live on a parallel lineage, while main independently adds PutBucketEncryption. Leaving the lineages separate prevents exact-tree qualification and publication of the complete provider-owned surface.

        Solution: integrate both composable lineages without narrowing either contract

        Retain every prepared initiator, provider-owned limited constructor, operation-last restart, typed Finish, synchronous wait, corpus, and qualification record from both sides. Reconcile the operation inventory at 52 provider operations and 49 prepared initiators while preserving the explicit three-call projection difference and all nonreplay, ownership, deadline, and certainty rules.

      8. 4401e0ec
        Problem: invalid-startup tests leak an admin credential into the checkout

        Configuration-rejection cases can reach credential bootstrap before failing, which leaves a generated credentials file in the repository root and dirties an otherwise clean qualification tree.

        Solution: isolate rejected-startup credentials in the test run directory

        Give every expected-failure launch its own credentials path under RUN_ROOT so bootstrap artifacts are removed with the maintained test workspace.

    7. 4401e0ec updated to 99706cceindex 91cc2b50

      1 source commit

      1. 99706cce
        Problem: bucket CORS stops at the client boundary

        PutBucketCors, GetBucketCors, and DeleteBucketCors have complete clients and signed corpora, but authenticated servers cannot execute them and no backend retains their state. Deployments therefore cannot provide the full configuration lifecycle even though callers can construct every request.

        Solution: complete bucket CORS across backends and server

        Add the backend-neutral canonical-document contract and implement atomic memory, files, and SQLite persistence. Route authenticated server PUT, GET, and DELETE with strict query, owner, checksum, XML, and absence handling. Advance SQLite to schema 13, add migration, corruption, symlink, capacity, restart, and 132-case abrupt-crash evidence, update compatibility and coverage, and qualify the exact tree through full tests, server/provider gates, GNATdoc, and 936/936 SPARK checks.

    8. 99706cce updated to 6ec20483index 4414c63a

      1 source commit

      1. 6ec20483
        Problem: Private ACL reads have no authenticated server route

        The qualified client and ACL codec cannot read bucket or object ACLs from Flyology servers, even though the existing single-tenant mutation profile admits only private ownership. Raw subresource routing must also prevent encoded ACL queries from falling through to ordinary mutations.

        Solution: Derive owner-only ACL responses in the S3 application

        Route authenticated GetBucketAcl and version-selecting GetObjectAcl calls to backend existence reads, synthesize the exact CanonicalUser FULL_CONTROL policy from the stable tenant principal, and reject ACL mutations without publication. Add strict query, authorization, owner, payer, body, error-classification, encoded-subresource, in-process, and real-server socket gates; promote only the server coverage cells while leaving ACL persistence unclaimed.

    Compare source revisions
    Development update

    flyology_object_storage_server 0.1.0-dev

    8 updates: 0761f9e2 through 6ec20483

    Supervised S3 server and management console for Flyology Object Storage

    Manifest fields
    origin
    Show all 8 updates
    1. 0761f9e2 updated to aa799686index 16142be3

      1 source commit

      1. aa799686
        Problem: clean hosted checkouts cannot complete the publication gates

        Strict Linux C compilation hides kill without an explicit POSIX feature contract, the proof project cannot locate an indirect Flyology project in Alire's shared cache, and shallow test checkouts cannot validate retained benchmark ancestry. The first public main CI therefore fails despite the locally qualified implementation.

        Solution: make clean-checkout requirements explicit

        Expose the POSIX.1-2008 declaration set locally in the durability bridge, prepend Alire's exported Flyology root only for maintained proof invocations, and fetch complete history for the test job that validates retained provenance.

    2. aa799686 updated to 98383e48index dee928e8

      1 source commit

      1. 98383e48
        Problem: clean hosted qualification depends on unused and fragile build paths

        Linux SQLite consumers inherit an unnecessary libm link from the optional FTS5 module, while the proof gate imports Flyology through a transitive cache location that Alire does not expose consistently in clean hosted workspaces. This prevents the published development line from completing its maintained SQLite and SPARK gates.

        Solution: narrow SQLite features and import the direct proof closure

        Disable the unused FTS5 extension instead of adding a compensating linker dependency. Make the proof project import the direct HTTP and XML project dependencies, and let the maintained script invoke GNATprove directly without reconstructing a transitive cache path.

    3. 98383e48 updated to 3455cde3index 8e99188e

      1 source commit

      1. 3455cde3
        Problem: proof-only checkouts resolve dependencies before materialization

        A clean hosted proof job invokes Alire execution before dependency build roots and generated configuration exist. The resulting GPR search path names directories that have not been synchronized, so GNATprove cannot load the direct HTTP and XML project closure.

        Solution: materialize the proof dependency closure before analysis

        Run Alire through the pre-build stage before GNATprove. This synchronizes dependencies and runs configuration actions without compiling the Object Storage library; GNATprove remains the analyzer for the selected proof units.

    4. 3455cde3 updated to 1978275bindex 27baef81

      5 source commits

      1. 09e6eac2
        Problem: DeleteBucket cannot compose with owner-driven callers

        The bucket lifecycle client exposes deletion only through blocking execution, so callers cannot share a Completion_Set and HTTP owner while retaining typed admission certainty across a possibly admitted mutation.

        Solution: Add one provider-owned non-replaying DeleteBucket operation

        Add the limited constructor, operation-last reusable initiation, typed Finish, and synchronous wait on one state machine. Use a non-rewindable empty source, bounded response retention, conservative deletion certainty, signed socket and normalization corpora, and maintainer documentation.

      2. 22fec71c
        Problem: GetBucketLocation cannot compose with owner-driven callers

        The bucket provider exposes only blocking location discovery even though callers need the raw bounded response while coordinating related operations in one Completion_Set. They must either block outside their state machine or bypass the provider-owned certainty, cancellation, and response-decoding contract.

        Solution: add one provider-owned bounded location read

        Add limited-root and operation-last Get_Location forms, a typed Finish result, and the matching prepared low-level initiator. Make the typed synchronous and legacy convenience overloads wait on the same bounded owner-driven state machine, preserve established defaults and legacy region normalization, retain no borrowed request input after signing, and leave safe GET recovery to Flyology HTTP. Gate exact response/failure normalization, expected-owner signing, fragmented XML, restart, documentation, full deterministic tests, and the warning-strict 936-check proof campaign.

      3. c0bae328
        Problem: GetBucketVersioning cannot compose with owner-driven callers

        Bucket-version reconciliation is available only through a blocking call, so structured callers cannot share a completion set, deadline, cancellation owner, or reusable operation while preserving the modeled response and HTTP failure evidence.

        Solution: add one provider-owned bounded versioning read

        Add limited-root and operation-last Get_Versioning forms with typed Finish in Client.Buckets, drive the prepared request through the shared HTTP state machine, retain XML under the versioning codec bound, preserve the established synchronous behavior, and qualify normalization, restart, documentation, and signed socket behavior.

      4. 39f97288
        Problem: PutBucketVersioning cannot compose without replay ambiguity

        Bucket-version updates are available only through blocking execution, so structured callers cannot own deadline, cancellation, and restart state or retain typed admission certainty for reconciliation.

        Solution: add one provider-owned nonreplaying versioning mutation

        Add limited-root and operation-last Set_Versioning_Configuration with typed Finish, move synchronous execution onto the same owned one-shot source, preserve exact certainty mapping, and qualify normalization, restart, documentation, signed sockets, and proof.

      5. 1978275b
        Problem: GetBucketPolicy cannot compose with owner-driven callers

        Bucket-policy retrieval is available only through blocking execution, so structured callers cannot retain typed HTTP state, caller-selected response bounds, cancellation, and restart ownership in a larger operation graph.

        Solution: add one provider-owned bounded policy read

        Add limited-root and operation-last Get_Policy with typed Finish, route the synchronous parameter-record overload through the same state machine, enforce exact prepared-operation identity, and qualify normalization, bounds, restart, documentation, signed sockets, and proof.

    5. 1978275b updated to 179b16c4index ade6ebbd

      9 source commits

      1. 0da1b4f7
        Problem: bucket policy mutations cannot join caller-owned operation graphs

        Callers can read bucket policies compositionally, but replacement and deletion still use separate blocking transport paths. That prevents provider-centric operation reuse, obscures admission certainty after ambiguous mutations, and leaves a socket-corpus startup failure able to strand clients before the server publishes its port.

        Solution: add provider-owned nonreplaying policy mutations

        Add limited Set_Policy and Delete_Policy roots, operation-last reusable initiation, typed Finish/results, exact low-level prepared-operation binding, and synchronous waits over the same one-shot state machines. Preserve owned payloads, caller-selected bounds, admission certainty, and read-only reconciliation rules; extend the signed corpus and make pre-publication server failure wake waiting clients deterministically.

      2. 5503d9d0
        Problem: Files benchmark durability provenance contradicts runtime policy

        The implementation manifest labels the Flyology files lane as not power durable even though its server uses the production durability policy. Campaign metadata also leaves that selected policy implicit, allowing later comparisons to overstate or misclassify durability equivalence.

        Solution: Pin and retain the production durability selection

        Label the matrix lane power-loss-durable, pass Power_Loss_Durable explicitly to the files server, record the exact commit policy in both retained matrix metadata streams, and gate the metadata field. Clarify the guide while leaving immutable historical evidence unchanged.

      3. 3453828c
        Problem: Public access controls cannot join composed client workflows

        PutPublicAccessBlock, GetPublicAccessBlock, and DeletePublicAccessBlock are available through synchronous helpers but not through the provider-owned operation model. Callers cannot compose these security controls with their completion sets, and mutation failures lack the typed certainty needed to choose read-only reconciliation without replay.

        Solution: Add provider-owned public access block operations

        Add limited constructors, operation-last restart procedures, typed Finish results, and synchronous waits on the same Client.Buckets state machines. Keep mutation bodies non-rewindable, preserve admission certainty and bounded same-response reads, reject mismatched prepared operations before HTTP admission, and cover lifecycle, restart, certainty, and documentation contracts.

      4. 551d514d
        Problem: Ownership controls reads cannot join composed client workflows

        Callers can retrieve bucket ownership controls only through the blocking low-level executor, so owner-driven operation graphs cannot compose the read, preserve typed HTTP failure context, or reuse an established parent operation.

        Solution: colocate bounded Ownership Controls reads with the Buckets provider

        Add limited and operation-last provider forms, typed Finish and synchronous waiting over the same state machine, an exact prepared-request initiator, bounded same-response decoding, restart and operation-identity tests, and matching architecture and compatibility evidence.

      5. 07269323
        Problem: Ownership controls writes cannot join composed client workflows

        PutBucketOwnershipControls is available only through a blocking executor, so owner-driven callers cannot retain typed admission certainty or reconcile ambiguous publication without leaving the provider API.

        Solution: add a non-replaying Ownership Controls mutation state machine

        Colocate limited, operation-last, Finish, and synchronous forms in Client.Buckets; expose an exact low-level initiator; retain serialized bytes through terminal drain; classify only response-observed exact rejections as definitely not applied; and gate operation identity, restart, wire behavior, and the complete admission-certainty matrix.

      6. 33b28a12
        Problem: Ownership controls deletion cannot join composed workflows

        DeleteBucketOwnershipControls still uses the generic blocking configuration path, so composed callers cannot retain typed admission certainty, reuse an established operation, or reconcile an ambiguous deletion through the owning provider.

        Solution: complete the provider-owned Ownership Controls trio

        Add a non-replaying Delete operation with limited and operation-last forms, typed Finish and synchronous waiting; rewrite the existing convenience call through that state machine; expose exact low-level initiation; and gate operation identity, restart, wire behavior, and exhaustive certainty normalization.

      7. da5c057f
        Problem: Bucket encryption reads cannot join composed workflows

        GetBucketEncryption is available only through the blocking executor, so owner-driven callers cannot compose its bounded response, cancellation, and deadline into an existing completion graph.

        Solution: Add a provider-owned Get_Encryption operation

        Add the exact low-level prepared initiator, limited and reusable provider overloads, typed Finish and synchronous wait over one bounded state machine. Cover exact-operation rejection, restart, response normalization, certainty, signed socket behavior, and document the expanded provider surface.

      8. e00ca596
        Problem: Bucket encryption deletion cannot join composed workflows

        DeleteBucketEncryption uses the blocking configuration dispatcher, so owner-driven callers cannot compose its one-shot mutation, deadline, cancellation, and admission certainty into an existing completion graph.

        Solution: Add a provider-owned Delete_Encryption operation

        Add the exact low-level initiator, limited and reusable provider overloads, typed Finish, and synchronous waits over one non-replaying state machine. Preserve the legacy Delete_Outcome surface through that same engine, remove its dead blocking branch, and cover exact binding, restart, certainty, response classes, and signed socket behavior.

      9. 179b16c4
        Problem: HTTP dependency oracles retain the pre-hook-selection origin

        The five no-pin solve roots now select the published HTTP/QUIC 0.1.3-dev source that removes hook preprocessing, while CI and maintained prose still assert the previous flattened-client origin.

        Solution: Advance the tracked HTTP origin qualification

        Update CI and maintainer documentation to exact eb09a80, retain exact current-dev constraints and no external pins, and align nearby composable terminology with the provider-centric API.

    6. 179b16c4 updated to 4401e0ecindex 4f7124b2

      8 source commits

      1. db16a412
        Problem: PutBucketCors cannot join composed client workflows

        The existing CORS client can read and delete configurations, but callers cannot publish a complete configuration through the provider-owned operation model. They cannot retain typed admission certainty, restart an established component, or prove that the exact modeled request graph is covered without falling back to a separate blocking path.

        Solution: add one provider-owned nonreplaying CORS mutation

        Serialize the pinned flattened CORS graph within caller-selected XML limits, prepare and execute one-shot signed requests, and colocate limited, operation-last, typed Finish, and synchronous Set_CORS forms in Client.Buckets. Add reciprocal model ledgers, deterministic and signed socket corpora, certainty normalization, coverage accounting, GNATdoc, and maintainer qualification evidence.

      2. df9d0d49
        Problem: CORS reads and deletions cannot join composed workflows

        GetBucketCors and DeleteBucketCors stop at synchronous execution even though their provider already owns exact prepared requests and bounded response decoding. Callers cannot reuse them inside completion-set state machines, and synchronous deletion does not share typed admission certainty with the composable client vocabulary.

        Solution: colocate composable CORS reads and deletions with Client.Buckets

        Add exact low-level initiators and provider-owned limited constructors, operation-last reusable procedures, typed Finish results, and synchronous waits on the same state machines. Preserve bounded decoding, non-replaying empty deletion bodies, admission certainty, and conservative outcome mapping, with signed socket, restart, mismatch, capacity, documentation, and normalization coverage.

      3. b30f0812
        Problem: Object Legal Hold cannot join composed client workflows

        GetObjectLegalHold and PutObjectLegalHold stop at blocking low-level execution, forcing callers to leave provider-owned completion sets and obscuring mutation admission certainty.

        Solution: colocate owner-driven Legal Hold operations in Client.Objects

        Add exact prepared-request initiators, limited constructors, operation-last restart, typed Finish, shared synchronous waits, an owned nonreplayable mutation source, bounded response sinks, certainty normalization, signed socket and negative corpora, and maintainer documentation.

      4. 1160fd60
        Problem: Object Retention cannot join composed client workflows

        GetObjectRetention and PutObjectRetention are available only through blocking client entry points, so completion-set state machines cannot compose exact-version retention reads or mutations without inventing a parallel wrapper. That obscures provider ownership and prevents typed admission certainty from flowing through caller-owned scheduling.

        Solution: colocate Retention operations with Client.Objects

        Add exact prepared-request initiators plus provider-owned limited constructors, operation-last reusable initiation, typed Finish, and synchronous waits driven by the same bounded state machines. Own the Put XML in a non-rewindable source, preserve conservative post-admission mutation certainty, require generation-bound read reconciliation, and gate restart, exact operation binding, normalization, and one-past response limits under native and lightweight owners.

      5. aa0a3693
        Problem: Object Lock configuration cannot join composed client workflows

        GetObjectLockConfiguration and PutObjectLockConfiguration expose only blocking execution, so completion-set state machines cannot own their lifetime, drain, certainty, and bounded response handling through the bucket provider.

        Solution: colocate owner-driven Object Lock configuration operations in Client.Buckets

        Add exact Low_Level prepared-request initiators, limited constructors, operation-last reusable procedures, typed Finish results, and synchronous waits over the same state machines. Preserve bounded same-response reads, one-shot non-replaying mutation ownership, conservative admission certainty, and read-only reconciliation, with strict socket, certainty, documentation, and API gates.

      6. d1dee5be
        Problem: PutBucketEncryption cannot join composed client workflows

        Callers can prepare and execute bucket-encryption updates synchronously, but they cannot schedule the mutation beside other owner-driven operations without rebuilding its signing, body-lifetime, and publication-certainty rules.

        Solution: add one nonreplaying provider-owned encryption mutation

        Serialize the pinned presence-sensitive configuration into caller-bounded XML, retain its exact signed bytes in the parent operation, expose limited and operation-last Set_Encryption forms with typed Finish, and make the synchronous form wait on that same state machine. Add reciprocal model inventories, deterministic and signed-socket corpora, certainty normalization coverage, qualification evidence, and honest client-only compatibility claims.

      7. 0956dcd3
        Problem: completed composable controls remain split from main

        The reviewed CORS, Object Lock configuration, Legal Hold, and Retention operation families live on a parallel lineage, while main independently adds PutBucketEncryption. Leaving the lineages separate prevents exact-tree qualification and publication of the complete provider-owned surface.

        Solution: integrate both composable lineages without narrowing either contract

        Retain every prepared initiator, provider-owned limited constructor, operation-last restart, typed Finish, synchronous wait, corpus, and qualification record from both sides. Reconcile the operation inventory at 52 provider operations and 49 prepared initiators while preserving the explicit three-call projection difference and all nonreplay, ownership, deadline, and certainty rules.

      8. 4401e0ec
        Problem: invalid-startup tests leak an admin credential into the checkout

        Configuration-rejection cases can reach credential bootstrap before failing, which leaves a generated credentials file in the repository root and dirties an otherwise clean qualification tree.

        Solution: isolate rejected-startup credentials in the test run directory

        Give every expected-failure launch its own credentials path under RUN_ROOT so bootstrap artifacts are removed with the maintained test workspace.

    7. 4401e0ec updated to 99706cceindex 91cc2b50

      1 source commit

      1. 99706cce
        Problem: bucket CORS stops at the client boundary

        PutBucketCors, GetBucketCors, and DeleteBucketCors have complete clients and signed corpora, but authenticated servers cannot execute them and no backend retains their state. Deployments therefore cannot provide the full configuration lifecycle even though callers can construct every request.

        Solution: complete bucket CORS across backends and server

        Add the backend-neutral canonical-document contract and implement atomic memory, files, and SQLite persistence. Route authenticated server PUT, GET, and DELETE with strict query, owner, checksum, XML, and absence handling. Advance SQLite to schema 13, add migration, corruption, symlink, capacity, restart, and 132-case abrupt-crash evidence, update compatibility and coverage, and qualify the exact tree through full tests, server/provider gates, GNATdoc, and 936/936 SPARK checks.

    8. 99706cce updated to 6ec20483index 4414c63a

      1 source commit

      1. 6ec20483
        Problem: Private ACL reads have no authenticated server route

        The qualified client and ACL codec cannot read bucket or object ACLs from Flyology servers, even though the existing single-tenant mutation profile admits only private ownership. Raw subresource routing must also prevent encoded ACL queries from falling through to ordinary mutations.

        Solution: Derive owner-only ACL responses in the S3 application

        Route authenticated GetBucketAcl and version-selecting GetObjectAcl calls to backend existence reads, synthesize the exact CanonicalUser FULL_CONTROL policy from the stable tenant principal, and reject ACL mutations without publication. Add strict query, authorization, owner, payer, body, error-classification, encoded-subresource, in-process, and real-server socket gates; promote only the server coverage cells while leaving ACL persistence unclaimed.

    Compare source revisions
    Development update

    flyology_object_storage_sqlite 0.1.0-dev

    8 updates: 0761f9e2 through 6ec20483

    SQLite catalog backend for Flyology Object Storage

    Manifest fields
    origin
    Show all 8 updates
    1. 0761f9e2 updated to aa799686index 16142be3

      1 source commit

      1. aa799686
        Problem: clean hosted checkouts cannot complete the publication gates

        Strict Linux C compilation hides kill without an explicit POSIX feature contract, the proof project cannot locate an indirect Flyology project in Alire's shared cache, and shallow test checkouts cannot validate retained benchmark ancestry. The first public main CI therefore fails despite the locally qualified implementation.

        Solution: make clean-checkout requirements explicit

        Expose the POSIX.1-2008 declaration set locally in the durability bridge, prepend Alire's exported Flyology root only for maintained proof invocations, and fetch complete history for the test job that validates retained provenance.

    2. aa799686 updated to 98383e48index dee928e8

      1 source commit

      1. 98383e48
        Problem: clean hosted qualification depends on unused and fragile build paths

        Linux SQLite consumers inherit an unnecessary libm link from the optional FTS5 module, while the proof gate imports Flyology through a transitive cache location that Alire does not expose consistently in clean hosted workspaces. This prevents the published development line from completing its maintained SQLite and SPARK gates.

        Solution: narrow SQLite features and import the direct proof closure

        Disable the unused FTS5 extension instead of adding a compensating linker dependency. Make the proof project import the direct HTTP and XML project dependencies, and let the maintained script invoke GNATprove directly without reconstructing a transitive cache path.

    3. 98383e48 updated to 3455cde3index 8e99188e

      1 source commit

      1. 3455cde3
        Problem: proof-only checkouts resolve dependencies before materialization

        A clean hosted proof job invokes Alire execution before dependency build roots and generated configuration exist. The resulting GPR search path names directories that have not been synchronized, so GNATprove cannot load the direct HTTP and XML project closure.

        Solution: materialize the proof dependency closure before analysis

        Run Alire through the pre-build stage before GNATprove. This synchronizes dependencies and runs configuration actions without compiling the Object Storage library; GNATprove remains the analyzer for the selected proof units.

    4. 3455cde3 updated to 1978275bindex 27baef81

      5 source commits

      1. 09e6eac2
        Problem: DeleteBucket cannot compose with owner-driven callers

        The bucket lifecycle client exposes deletion only through blocking execution, so callers cannot share a Completion_Set and HTTP owner while retaining typed admission certainty across a possibly admitted mutation.

        Solution: Add one provider-owned non-replaying DeleteBucket operation

        Add the limited constructor, operation-last reusable initiation, typed Finish, and synchronous wait on one state machine. Use a non-rewindable empty source, bounded response retention, conservative deletion certainty, signed socket and normalization corpora, and maintainer documentation.

      2. 22fec71c
        Problem: GetBucketLocation cannot compose with owner-driven callers

        The bucket provider exposes only blocking location discovery even though callers need the raw bounded response while coordinating related operations in one Completion_Set. They must either block outside their state machine or bypass the provider-owned certainty, cancellation, and response-decoding contract.

        Solution: add one provider-owned bounded location read

        Add limited-root and operation-last Get_Location forms, a typed Finish result, and the matching prepared low-level initiator. Make the typed synchronous and legacy convenience overloads wait on the same bounded owner-driven state machine, preserve established defaults and legacy region normalization, retain no borrowed request input after signing, and leave safe GET recovery to Flyology HTTP. Gate exact response/failure normalization, expected-owner signing, fragmented XML, restart, documentation, full deterministic tests, and the warning-strict 936-check proof campaign.

      3. c0bae328
        Problem: GetBucketVersioning cannot compose with owner-driven callers

        Bucket-version reconciliation is available only through a blocking call, so structured callers cannot share a completion set, deadline, cancellation owner, or reusable operation while preserving the modeled response and HTTP failure evidence.

        Solution: add one provider-owned bounded versioning read

        Add limited-root and operation-last Get_Versioning forms with typed Finish in Client.Buckets, drive the prepared request through the shared HTTP state machine, retain XML under the versioning codec bound, preserve the established synchronous behavior, and qualify normalization, restart, documentation, and signed socket behavior.

      4. 39f97288
        Problem: PutBucketVersioning cannot compose without replay ambiguity

        Bucket-version updates are available only through blocking execution, so structured callers cannot own deadline, cancellation, and restart state or retain typed admission certainty for reconciliation.

        Solution: add one provider-owned nonreplaying versioning mutation

        Add limited-root and operation-last Set_Versioning_Configuration with typed Finish, move synchronous execution onto the same owned one-shot source, preserve exact certainty mapping, and qualify normalization, restart, documentation, signed sockets, and proof.

      5. 1978275b
        Problem: GetBucketPolicy cannot compose with owner-driven callers

        Bucket-policy retrieval is available only through blocking execution, so structured callers cannot retain typed HTTP state, caller-selected response bounds, cancellation, and restart ownership in a larger operation graph.

        Solution: add one provider-owned bounded policy read

        Add limited-root and operation-last Get_Policy with typed Finish, route the synchronous parameter-record overload through the same state machine, enforce exact prepared-operation identity, and qualify normalization, bounds, restart, documentation, signed sockets, and proof.

    5. 1978275b updated to 179b16c4index ade6ebbd

      9 source commits

      1. 0da1b4f7
        Problem: bucket policy mutations cannot join caller-owned operation graphs

        Callers can read bucket policies compositionally, but replacement and deletion still use separate blocking transport paths. That prevents provider-centric operation reuse, obscures admission certainty after ambiguous mutations, and leaves a socket-corpus startup failure able to strand clients before the server publishes its port.

        Solution: add provider-owned nonreplaying policy mutations

        Add limited Set_Policy and Delete_Policy roots, operation-last reusable initiation, typed Finish/results, exact low-level prepared-operation binding, and synchronous waits over the same one-shot state machines. Preserve owned payloads, caller-selected bounds, admission certainty, and read-only reconciliation rules; extend the signed corpus and make pre-publication server failure wake waiting clients deterministically.

      2. 5503d9d0
        Problem: Files benchmark durability provenance contradicts runtime policy

        The implementation manifest labels the Flyology files lane as not power durable even though its server uses the production durability policy. Campaign metadata also leaves that selected policy implicit, allowing later comparisons to overstate or misclassify durability equivalence.

        Solution: Pin and retain the production durability selection

        Label the matrix lane power-loss-durable, pass Power_Loss_Durable explicitly to the files server, record the exact commit policy in both retained matrix metadata streams, and gate the metadata field. Clarify the guide while leaving immutable historical evidence unchanged.

      3. 3453828c
        Problem: Public access controls cannot join composed client workflows

        PutPublicAccessBlock, GetPublicAccessBlock, and DeletePublicAccessBlock are available through synchronous helpers but not through the provider-owned operation model. Callers cannot compose these security controls with their completion sets, and mutation failures lack the typed certainty needed to choose read-only reconciliation without replay.

        Solution: Add provider-owned public access block operations

        Add limited constructors, operation-last restart procedures, typed Finish results, and synchronous waits on the same Client.Buckets state machines. Keep mutation bodies non-rewindable, preserve admission certainty and bounded same-response reads, reject mismatched prepared operations before HTTP admission, and cover lifecycle, restart, certainty, and documentation contracts.

      4. 551d514d
        Problem: Ownership controls reads cannot join composed client workflows

        Callers can retrieve bucket ownership controls only through the blocking low-level executor, so owner-driven operation graphs cannot compose the read, preserve typed HTTP failure context, or reuse an established parent operation.

        Solution: colocate bounded Ownership Controls reads with the Buckets provider

        Add limited and operation-last provider forms, typed Finish and synchronous waiting over the same state machine, an exact prepared-request initiator, bounded same-response decoding, restart and operation-identity tests, and matching architecture and compatibility evidence.

      5. 07269323
        Problem: Ownership controls writes cannot join composed client workflows

        PutBucketOwnershipControls is available only through a blocking executor, so owner-driven callers cannot retain typed admission certainty or reconcile ambiguous publication without leaving the provider API.

        Solution: add a non-replaying Ownership Controls mutation state machine

        Colocate limited, operation-last, Finish, and synchronous forms in Client.Buckets; expose an exact low-level initiator; retain serialized bytes through terminal drain; classify only response-observed exact rejections as definitely not applied; and gate operation identity, restart, wire behavior, and the complete admission-certainty matrix.

      6. 33b28a12
        Problem: Ownership controls deletion cannot join composed workflows

        DeleteBucketOwnershipControls still uses the generic blocking configuration path, so composed callers cannot retain typed admission certainty, reuse an established operation, or reconcile an ambiguous deletion through the owning provider.

        Solution: complete the provider-owned Ownership Controls trio

        Add a non-replaying Delete operation with limited and operation-last forms, typed Finish and synchronous waiting; rewrite the existing convenience call through that state machine; expose exact low-level initiation; and gate operation identity, restart, wire behavior, and exhaustive certainty normalization.

      7. da5c057f
        Problem: Bucket encryption reads cannot join composed workflows

        GetBucketEncryption is available only through the blocking executor, so owner-driven callers cannot compose its bounded response, cancellation, and deadline into an existing completion graph.

        Solution: Add a provider-owned Get_Encryption operation

        Add the exact low-level prepared initiator, limited and reusable provider overloads, typed Finish and synchronous wait over one bounded state machine. Cover exact-operation rejection, restart, response normalization, certainty, signed socket behavior, and document the expanded provider surface.

      8. e00ca596
        Problem: Bucket encryption deletion cannot join composed workflows

        DeleteBucketEncryption uses the blocking configuration dispatcher, so owner-driven callers cannot compose its one-shot mutation, deadline, cancellation, and admission certainty into an existing completion graph.

        Solution: Add a provider-owned Delete_Encryption operation

        Add the exact low-level initiator, limited and reusable provider overloads, typed Finish, and synchronous waits over one non-replaying state machine. Preserve the legacy Delete_Outcome surface through that same engine, remove its dead blocking branch, and cover exact binding, restart, certainty, response classes, and signed socket behavior.

      9. 179b16c4
        Problem: HTTP dependency oracles retain the pre-hook-selection origin

        The five no-pin solve roots now select the published HTTP/QUIC 0.1.3-dev source that removes hook preprocessing, while CI and maintained prose still assert the previous flattened-client origin.

        Solution: Advance the tracked HTTP origin qualification

        Update CI and maintainer documentation to exact eb09a80, retain exact current-dev constraints and no external pins, and align nearby composable terminology with the provider-centric API.

    6. 179b16c4 updated to 4401e0ecindex 4f7124b2

      8 source commits

      1. db16a412
        Problem: PutBucketCors cannot join composed client workflows

        The existing CORS client can read and delete configurations, but callers cannot publish a complete configuration through the provider-owned operation model. They cannot retain typed admission certainty, restart an established component, or prove that the exact modeled request graph is covered without falling back to a separate blocking path.

        Solution: add one provider-owned nonreplaying CORS mutation

        Serialize the pinned flattened CORS graph within caller-selected XML limits, prepare and execute one-shot signed requests, and colocate limited, operation-last, typed Finish, and synchronous Set_CORS forms in Client.Buckets. Add reciprocal model ledgers, deterministic and signed socket corpora, certainty normalization, coverage accounting, GNATdoc, and maintainer qualification evidence.

      2. df9d0d49
        Problem: CORS reads and deletions cannot join composed workflows

        GetBucketCors and DeleteBucketCors stop at synchronous execution even though their provider already owns exact prepared requests and bounded response decoding. Callers cannot reuse them inside completion-set state machines, and synchronous deletion does not share typed admission certainty with the composable client vocabulary.

        Solution: colocate composable CORS reads and deletions with Client.Buckets

        Add exact low-level initiators and provider-owned limited constructors, operation-last reusable procedures, typed Finish results, and synchronous waits on the same state machines. Preserve bounded decoding, non-replaying empty deletion bodies, admission certainty, and conservative outcome mapping, with signed socket, restart, mismatch, capacity, documentation, and normalization coverage.

      3. b30f0812
        Problem: Object Legal Hold cannot join composed client workflows

        GetObjectLegalHold and PutObjectLegalHold stop at blocking low-level execution, forcing callers to leave provider-owned completion sets and obscuring mutation admission certainty.

        Solution: colocate owner-driven Legal Hold operations in Client.Objects

        Add exact prepared-request initiators, limited constructors, operation-last restart, typed Finish, shared synchronous waits, an owned nonreplayable mutation source, bounded response sinks, certainty normalization, signed socket and negative corpora, and maintainer documentation.

      4. 1160fd60
        Problem: Object Retention cannot join composed client workflows

        GetObjectRetention and PutObjectRetention are available only through blocking client entry points, so completion-set state machines cannot compose exact-version retention reads or mutations without inventing a parallel wrapper. That obscures provider ownership and prevents typed admission certainty from flowing through caller-owned scheduling.

        Solution: colocate Retention operations with Client.Objects

        Add exact prepared-request initiators plus provider-owned limited constructors, operation-last reusable initiation, typed Finish, and synchronous waits driven by the same bounded state machines. Own the Put XML in a non-rewindable source, preserve conservative post-admission mutation certainty, require generation-bound read reconciliation, and gate restart, exact operation binding, normalization, and one-past response limits under native and lightweight owners.

      5. aa0a3693
        Problem: Object Lock configuration cannot join composed client workflows

        GetObjectLockConfiguration and PutObjectLockConfiguration expose only blocking execution, so completion-set state machines cannot own their lifetime, drain, certainty, and bounded response handling through the bucket provider.

        Solution: colocate owner-driven Object Lock configuration operations in Client.Buckets

        Add exact Low_Level prepared-request initiators, limited constructors, operation-last reusable procedures, typed Finish results, and synchronous waits over the same state machines. Preserve bounded same-response reads, one-shot non-replaying mutation ownership, conservative admission certainty, and read-only reconciliation, with strict socket, certainty, documentation, and API gates.

      6. d1dee5be
        Problem: PutBucketEncryption cannot join composed client workflows

        Callers can prepare and execute bucket-encryption updates synchronously, but they cannot schedule the mutation beside other owner-driven operations without rebuilding its signing, body-lifetime, and publication-certainty rules.

        Solution: add one nonreplaying provider-owned encryption mutation

        Serialize the pinned presence-sensitive configuration into caller-bounded XML, retain its exact signed bytes in the parent operation, expose limited and operation-last Set_Encryption forms with typed Finish, and make the synchronous form wait on that same state machine. Add reciprocal model inventories, deterministic and signed-socket corpora, certainty normalization coverage, qualification evidence, and honest client-only compatibility claims.

      7. 0956dcd3
        Problem: completed composable controls remain split from main

        The reviewed CORS, Object Lock configuration, Legal Hold, and Retention operation families live on a parallel lineage, while main independently adds PutBucketEncryption. Leaving the lineages separate prevents exact-tree qualification and publication of the complete provider-owned surface.

        Solution: integrate both composable lineages without narrowing either contract

        Retain every prepared initiator, provider-owned limited constructor, operation-last restart, typed Finish, synchronous wait, corpus, and qualification record from both sides. Reconcile the operation inventory at 52 provider operations and 49 prepared initiators while preserving the explicit three-call projection difference and all nonreplay, ownership, deadline, and certainty rules.

      8. 4401e0ec
        Problem: invalid-startup tests leak an admin credential into the checkout

        Configuration-rejection cases can reach credential bootstrap before failing, which leaves a generated credentials file in the repository root and dirties an otherwise clean qualification tree.

        Solution: isolate rejected-startup credentials in the test run directory

        Give every expected-failure launch its own credentials path under RUN_ROOT so bootstrap artifacts are removed with the maintained test workspace.

    7. 4401e0ec updated to 99706cceindex 91cc2b50

      1 source commit

      1. 99706cce
        Problem: bucket CORS stops at the client boundary

        PutBucketCors, GetBucketCors, and DeleteBucketCors have complete clients and signed corpora, but authenticated servers cannot execute them and no backend retains their state. Deployments therefore cannot provide the full configuration lifecycle even though callers can construct every request.

        Solution: complete bucket CORS across backends and server

        Add the backend-neutral canonical-document contract and implement atomic memory, files, and SQLite persistence. Route authenticated server PUT, GET, and DELETE with strict query, owner, checksum, XML, and absence handling. Advance SQLite to schema 13, add migration, corruption, symlink, capacity, restart, and 132-case abrupt-crash evidence, update compatibility and coverage, and qualify the exact tree through full tests, server/provider gates, GNATdoc, and 936/936 SPARK checks.

    8. 99706cce updated to 6ec20483index 4414c63a

      1 source commit

      1. 6ec20483
        Problem: Private ACL reads have no authenticated server route

        The qualified client and ACL codec cannot read bucket or object ACLs from Flyology servers, even though the existing single-tenant mutation profile admits only private ownership. Raw subresource routing must also prevent encoded ACL queries from falling through to ordinary mutations.

        Solution: Derive owner-only ACL responses in the S3 application

        Route authenticated GetBucketAcl and version-selecting GetObjectAcl calls to backend existence reads, synthesize the exact CanonicalUser FULL_CONTROL policy from the stable tenant principal, and reject ACL mutations without publication. Add strict query, authorization, owner, payer, body, error-classification, encoded-subresource, in-process, and real-server socket gates; promote only the server coverage cells while leaving ACL persistence unclaimed.

    Compare source revisions
  13. publish flyology_json 0.1.0-dev

    56939882 on GitHub
  14. Advance development source pins

    8b8fdf03 on GitHub
  15. publish the Object Storage 0.1.0-dev source group

    b454736c on GitHub
  16. Development updates

    Development update

    flyology 0.1.1-dev

    2 updates: 243833e6 through 3859f412

    Experimental GNAT runtime extension for native and lightweight Ada tasks

    Manifest fields
    origin
    Show all 2 updates
    1. 243833e6 updated to 810f1088index 36533e23

      8 source commits

      1. 86f831cc
        Problem: Buffer slots can reenter the free pool at their final generation

        A slot whose nonwrapping generation reaches its maximum is released back into the free stack. Its next acquisition fails after the pool has already removed it, corrupting availability and potentially leaving waiters with inconsistent accounting. The remoting buffer-domain work depends on generation-safe capability reuse.

        Solution: Retire slots after their final published generation

        Preflight generation exhaustion before mutating allocation state, omit final-generation slots from the free stack on release, document permanent retirement, and add a statically elided test seam that exercises near-wrap behavior. The regression covers surviving capacity, complete retirement, nonblocking and timed acquisition, coverage integration, and production hook-symbol elision.

      2. 06bbc9c0
        Problem: Runtime-selected buffer pools cannot carry ownership without stored pool access

        Remoting sessions need to choose among heterogeneous buffer pools while moving payload ownership through definite transport capabilities. A pool-bound buffer alone either exposes an access value across the driver boundary or loses the lifetime, domain, and exception-atomicity guarantees needed for zero-copy delivery.

        Solution: Add domain-bound heterogeneous buffer capabilities

        Introduce an immutable buffer-domain catalogue with opaque pool references and access-free driver capabilities. Ownership transfers use abort-deferred protected commits, domain-bound public owners retain compile-time lifetime checks, and all storage access validates the supplied domain. Add wrong-domain, zero-copy, finalization, rollback, hook-elision, and compile-negative lifetime coverage.

      3. 50b84004
        Problem: Remoting header pools cannot be reserved across abort-safe session cleanup

        A remoting session needs exclusive ownership of one heterogeneous buffer pool while messages are in flight, but the existing domain admitted only ordinary acquisitions. It had no bounded reservation claims, generation-safe delayed release, or authority token for acknowledging a retired session after its final context-state cut. Base buffer acquisition and release also published ownership through protected-call copy-out boundaries that could lose recovery authority under abort.

        Solution: Add bounded generation-stamped buffer pool reservations

        Add controlled reservation claims and authorized release tokens, exact reservation provenance on buffers and capabilities, total acquisition statuses, nonwrapping generations, pending-release reissue, and permanent exhaustion. Publish and clear actual ownership tokens inside protected actions, retain abort-safe cleanup guards, document lock and lifecycle rules, and cover failure boundaries, provenance, finalization, status precedence, lifetime rejection, and production hook elision.

      4. a4ab6d4b
        Problem: Context publication cannot move domain capabilities without nesting protected locks

        A remoting context must publish a reserved header and an ordinary payload as one abort-deferred ownership transition. The validated buffer operations re-enter the domain gate, so calling them while the context registry is protected would invert the lock boundary and leave no safe compound commit point.

        Solution: Add prevalidated direct capability commit moves

        Add provider-only limited ownership moves whose bodies contain only same-subtype field transfers and source clearing. Document the caller-owned validation and publication cut, cover heterogeneous pool provenance, tags, bytes, rejection, and abort behavior, and make the root suite fail closed on any unreviewed helper instruction or retained test hook.

      5. f387f8ec
        Problem: Production hook checks reject the disabled buffer hook package

        The disabled test-hook variant necessarily contributes its package elaboration and literal Enabled symbols to the production archive. The behavioral suite matches the package prefix broadly, so a clean production build fails before the repository can verify the new buffer-domain boundary.

        Solution: Match only executable buffer test seams

        Restrict the archive classifier to the arm, consume, note, and live hook operations plus the imported disabled sentinels. This keeps surviving test behavior detectable without treating the inert disabled package metadata as production test code.

      6. c9125bed
        Problem: Buffer domain API fails strict documentation verification

        The new domain catalogue, sentinels, acquisition results, reservation overloads, and private controlled-operation helpers lack complete GNATdoc annotations. Strict API generation therefore rejects the reviewed dependency series and cannot publish its public contract.

        Solution: Complete buffer domain API annotations

        Document every new public entity and result literal, describe each reservation overload formal, and exclude private implementation helpers while documenting their formals as required by GNATdoc. Format the specification with the owning Flyology project settings.

      7. 5c3d43c4
        Problem: Buffer acquisition status docs overstate reservation state

        The generated API describes Reservation_Not_Active as never published even though a previously published exact generation can later become inactive. It also attributes the bounded claim capacity to a reservation although ordinary unreserved acquisitions share the same pool claim bound.

        Solution: Describe status outcomes by current pool state

        Define Reservation_Not_Active in terms of the exact generation currently being inactive and attribute Claim_Limit_Reached to the pool claim capacity. The wording now matches the implemented and tested status paths.

      8. 810f1088
        Merge pull request #83 from flyology-ada/codex/remoting-buffer-domain-publish

        Add abort-safe heterogeneous buffer domains for remoting

    2. 810f1088 updated to 3859f412index ba75376c

      2 source commits

      1. 84b425b1
        Problem: External consumers do not verify buffer-domain publication

        The out-of-tree consumer does not reference the buffer-domain packages. A stale exact-version Alire lock can therefore supply a pre-domain Flyology source tree while the consumer still builds, leaving the published dependency surface unverified.

        Solution: Compile the buffer-domain API out of tree

        Make the external consumer import Domains and Domains.Drivers, acquire and release a domain-owned buffer, and call the driver diagnostic so the two package specifications and bodies must be packaged, compiled, and linked.

      2. 3859f412
        Merge pull request #84 from flyology-ada/codex/buffer-domain-external-consumer

        Verify buffer-domain API from an external consumer

    Compare source revisions
    Development update

    flyology_allocators 0.1.0-dev

    2 updates: 243833e6 through 3859f412

    Caller-owned memory allocation algorithms for Ada

    Manifest fields
    origin
    Show all 2 updates
    1. 243833e6 updated to 810f1088index 36533e23

      8 source commits

      1. 86f831cc
        Problem: Buffer slots can reenter the free pool at their final generation

        A slot whose nonwrapping generation reaches its maximum is released back into the free stack. Its next acquisition fails after the pool has already removed it, corrupting availability and potentially leaving waiters with inconsistent accounting. The remoting buffer-domain work depends on generation-safe capability reuse.

        Solution: Retire slots after their final published generation

        Preflight generation exhaustion before mutating allocation state, omit final-generation slots from the free stack on release, document permanent retirement, and add a statically elided test seam that exercises near-wrap behavior. The regression covers surviving capacity, complete retirement, nonblocking and timed acquisition, coverage integration, and production hook-symbol elision.

      2. 06bbc9c0
        Problem: Runtime-selected buffer pools cannot carry ownership without stored pool access

        Remoting sessions need to choose among heterogeneous buffer pools while moving payload ownership through definite transport capabilities. A pool-bound buffer alone either exposes an access value across the driver boundary or loses the lifetime, domain, and exception-atomicity guarantees needed for zero-copy delivery.

        Solution: Add domain-bound heterogeneous buffer capabilities

        Introduce an immutable buffer-domain catalogue with opaque pool references and access-free driver capabilities. Ownership transfers use abort-deferred protected commits, domain-bound public owners retain compile-time lifetime checks, and all storage access validates the supplied domain. Add wrong-domain, zero-copy, finalization, rollback, hook-elision, and compile-negative lifetime coverage.

      3. 50b84004
        Problem: Remoting header pools cannot be reserved across abort-safe session cleanup

        A remoting session needs exclusive ownership of one heterogeneous buffer pool while messages are in flight, but the existing domain admitted only ordinary acquisitions. It had no bounded reservation claims, generation-safe delayed release, or authority token for acknowledging a retired session after its final context-state cut. Base buffer acquisition and release also published ownership through protected-call copy-out boundaries that could lose recovery authority under abort.

        Solution: Add bounded generation-stamped buffer pool reservations

        Add controlled reservation claims and authorized release tokens, exact reservation provenance on buffers and capabilities, total acquisition statuses, nonwrapping generations, pending-release reissue, and permanent exhaustion. Publish and clear actual ownership tokens inside protected actions, retain abort-safe cleanup guards, document lock and lifecycle rules, and cover failure boundaries, provenance, finalization, status precedence, lifetime rejection, and production hook elision.

      4. a4ab6d4b
        Problem: Context publication cannot move domain capabilities without nesting protected locks

        A remoting context must publish a reserved header and an ordinary payload as one abort-deferred ownership transition. The validated buffer operations re-enter the domain gate, so calling them while the context registry is protected would invert the lock boundary and leave no safe compound commit point.

        Solution: Add prevalidated direct capability commit moves

        Add provider-only limited ownership moves whose bodies contain only same-subtype field transfers and source clearing. Document the caller-owned validation and publication cut, cover heterogeneous pool provenance, tags, bytes, rejection, and abort behavior, and make the root suite fail closed on any unreviewed helper instruction or retained test hook.

      5. f387f8ec
        Problem: Production hook checks reject the disabled buffer hook package

        The disabled test-hook variant necessarily contributes its package elaboration and literal Enabled symbols to the production archive. The behavioral suite matches the package prefix broadly, so a clean production build fails before the repository can verify the new buffer-domain boundary.

        Solution: Match only executable buffer test seams

        Restrict the archive classifier to the arm, consume, note, and live hook operations plus the imported disabled sentinels. This keeps surviving test behavior detectable without treating the inert disabled package metadata as production test code.

      6. c9125bed
        Problem: Buffer domain API fails strict documentation verification

        The new domain catalogue, sentinels, acquisition results, reservation overloads, and private controlled-operation helpers lack complete GNATdoc annotations. Strict API generation therefore rejects the reviewed dependency series and cannot publish its public contract.

        Solution: Complete buffer domain API annotations

        Document every new public entity and result literal, describe each reservation overload formal, and exclude private implementation helpers while documenting their formals as required by GNATdoc. Format the specification with the owning Flyology project settings.

      7. 5c3d43c4
        Problem: Buffer acquisition status docs overstate reservation state

        The generated API describes Reservation_Not_Active as never published even though a previously published exact generation can later become inactive. It also attributes the bounded claim capacity to a reservation although ordinary unreserved acquisitions share the same pool claim bound.

        Solution: Describe status outcomes by current pool state

        Define Reservation_Not_Active in terms of the exact generation currently being inactive and attribute Claim_Limit_Reached to the pool claim capacity. The wording now matches the implemented and tested status paths.

      8. 810f1088
        Merge pull request #83 from flyology-ada/codex/remoting-buffer-domain-publish

        Add abort-safe heterogeneous buffer domains for remoting

    2. 810f1088 updated to 3859f412index ba75376c

      2 source commits

      1. 84b425b1
        Problem: External consumers do not verify buffer-domain publication

        The out-of-tree consumer does not reference the buffer-domain packages. A stale exact-version Alire lock can therefore supply a pre-domain Flyology source tree while the consumer still builds, leaving the published dependency surface unverified.

        Solution: Compile the buffer-domain API out of tree

        Make the external consumer import Domains and Domains.Drivers, acquire and release a domain-owned buffer, and call the driver diagnostic so the two package specifications and bodies must be packaged, compiled, and linked.

      2. 3859f412
        Merge pull request #84 from flyology-ada/codex/buffer-domain-external-consumer

        Verify buffer-domain API from an external consumer

    Compare source revisions
    Development update

    flyology_bench 0.1.1-dev

    2 updates: 243833e6 through 3859f412

    Adaptive nanosecond-scale benchmarking for Ada

    Manifest fields
    origin
    Show all 2 updates
    1. 243833e6 updated to 810f1088index 36533e23

      8 source commits

      1. 86f831cc
        Problem: Buffer slots can reenter the free pool at their final generation

        A slot whose nonwrapping generation reaches its maximum is released back into the free stack. Its next acquisition fails after the pool has already removed it, corrupting availability and potentially leaving waiters with inconsistent accounting. The remoting buffer-domain work depends on generation-safe capability reuse.

        Solution: Retire slots after their final published generation

        Preflight generation exhaustion before mutating allocation state, omit final-generation slots from the free stack on release, document permanent retirement, and add a statically elided test seam that exercises near-wrap behavior. The regression covers surviving capacity, complete retirement, nonblocking and timed acquisition, coverage integration, and production hook-symbol elision.

      2. 06bbc9c0
        Problem: Runtime-selected buffer pools cannot carry ownership without stored pool access

        Remoting sessions need to choose among heterogeneous buffer pools while moving payload ownership through definite transport capabilities. A pool-bound buffer alone either exposes an access value across the driver boundary or loses the lifetime, domain, and exception-atomicity guarantees needed for zero-copy delivery.

        Solution: Add domain-bound heterogeneous buffer capabilities

        Introduce an immutable buffer-domain catalogue with opaque pool references and access-free driver capabilities. Ownership transfers use abort-deferred protected commits, domain-bound public owners retain compile-time lifetime checks, and all storage access validates the supplied domain. Add wrong-domain, zero-copy, finalization, rollback, hook-elision, and compile-negative lifetime coverage.

      3. 50b84004
        Problem: Remoting header pools cannot be reserved across abort-safe session cleanup

        A remoting session needs exclusive ownership of one heterogeneous buffer pool while messages are in flight, but the existing domain admitted only ordinary acquisitions. It had no bounded reservation claims, generation-safe delayed release, or authority token for acknowledging a retired session after its final context-state cut. Base buffer acquisition and release also published ownership through protected-call copy-out boundaries that could lose recovery authority under abort.

        Solution: Add bounded generation-stamped buffer pool reservations

        Add controlled reservation claims and authorized release tokens, exact reservation provenance on buffers and capabilities, total acquisition statuses, nonwrapping generations, pending-release reissue, and permanent exhaustion. Publish and clear actual ownership tokens inside protected actions, retain abort-safe cleanup guards, document lock and lifecycle rules, and cover failure boundaries, provenance, finalization, status precedence, lifetime rejection, and production hook elision.

      4. a4ab6d4b
        Problem: Context publication cannot move domain capabilities without nesting protected locks

        A remoting context must publish a reserved header and an ordinary payload as one abort-deferred ownership transition. The validated buffer operations re-enter the domain gate, so calling them while the context registry is protected would invert the lock boundary and leave no safe compound commit point.

        Solution: Add prevalidated direct capability commit moves

        Add provider-only limited ownership moves whose bodies contain only same-subtype field transfers and source clearing. Document the caller-owned validation and publication cut, cover heterogeneous pool provenance, tags, bytes, rejection, and abort behavior, and make the root suite fail closed on any unreviewed helper instruction or retained test hook.

      5. f387f8ec
        Problem: Production hook checks reject the disabled buffer hook package

        The disabled test-hook variant necessarily contributes its package elaboration and literal Enabled symbols to the production archive. The behavioral suite matches the package prefix broadly, so a clean production build fails before the repository can verify the new buffer-domain boundary.

        Solution: Match only executable buffer test seams

        Restrict the archive classifier to the arm, consume, note, and live hook operations plus the imported disabled sentinels. This keeps surviving test behavior detectable without treating the inert disabled package metadata as production test code.

      6. c9125bed
        Problem: Buffer domain API fails strict documentation verification

        The new domain catalogue, sentinels, acquisition results, reservation overloads, and private controlled-operation helpers lack complete GNATdoc annotations. Strict API generation therefore rejects the reviewed dependency series and cannot publish its public contract.

        Solution: Complete buffer domain API annotations

        Document every new public entity and result literal, describe each reservation overload formal, and exclude private implementation helpers while documenting their formals as required by GNATdoc. Format the specification with the owning Flyology project settings.

      7. 5c3d43c4
        Problem: Buffer acquisition status docs overstate reservation state

        The generated API describes Reservation_Not_Active as never published even though a previously published exact generation can later become inactive. It also attributes the bounded claim capacity to a reservation although ordinary unreserved acquisitions share the same pool claim bound.

        Solution: Describe status outcomes by current pool state

        Define Reservation_Not_Active in terms of the exact generation currently being inactive and attribute Claim_Limit_Reached to the pool claim capacity. The wording now matches the implemented and tested status paths.

      8. 810f1088
        Merge pull request #83 from flyology-ada/codex/remoting-buffer-domain-publish

        Add abort-safe heterogeneous buffer domains for remoting

    2. 810f1088 updated to 3859f412index ba75376c

      2 source commits

      1. 84b425b1
        Problem: External consumers do not verify buffer-domain publication

        The out-of-tree consumer does not reference the buffer-domain packages. A stale exact-version Alire lock can therefore supply a pre-domain Flyology source tree while the consumer still builds, leaving the published dependency surface unverified.

        Solution: Compile the buffer-domain API out of tree

        Make the external consumer import Domains and Domains.Drivers, acquire and release a domain-owned buffer, and call the driver diagnostic so the two package specifications and bodies must be packaged, compiled, and linked.

      2. 3859f412
        Merge pull request #84 from flyology-ada/codex/buffer-domain-external-consumer

        Verify buffer-domain API from an external consumer

    Compare source revisions
    Development update

    flyology_cachelines 0.1.1-dev

    2 updates: 243833e6 through 3859f412

    Cache-line-aware storage and cache information for Ada

    Manifest fields
    origin
    Show all 2 updates
    1. 243833e6 updated to 810f1088index 36533e23

      8 source commits

      1. 86f831cc
        Problem: Buffer slots can reenter the free pool at their final generation

        A slot whose nonwrapping generation reaches its maximum is released back into the free stack. Its next acquisition fails after the pool has already removed it, corrupting availability and potentially leaving waiters with inconsistent accounting. The remoting buffer-domain work depends on generation-safe capability reuse.

        Solution: Retire slots after their final published generation

        Preflight generation exhaustion before mutating allocation state, omit final-generation slots from the free stack on release, document permanent retirement, and add a statically elided test seam that exercises near-wrap behavior. The regression covers surviving capacity, complete retirement, nonblocking and timed acquisition, coverage integration, and production hook-symbol elision.

      2. 06bbc9c0
        Problem: Runtime-selected buffer pools cannot carry ownership without stored pool access

        Remoting sessions need to choose among heterogeneous buffer pools while moving payload ownership through definite transport capabilities. A pool-bound buffer alone either exposes an access value across the driver boundary or loses the lifetime, domain, and exception-atomicity guarantees needed for zero-copy delivery.

        Solution: Add domain-bound heterogeneous buffer capabilities

        Introduce an immutable buffer-domain catalogue with opaque pool references and access-free driver capabilities. Ownership transfers use abort-deferred protected commits, domain-bound public owners retain compile-time lifetime checks, and all storage access validates the supplied domain. Add wrong-domain, zero-copy, finalization, rollback, hook-elision, and compile-negative lifetime coverage.

      3. 50b84004
        Problem: Remoting header pools cannot be reserved across abort-safe session cleanup

        A remoting session needs exclusive ownership of one heterogeneous buffer pool while messages are in flight, but the existing domain admitted only ordinary acquisitions. It had no bounded reservation claims, generation-safe delayed release, or authority token for acknowledging a retired session after its final context-state cut. Base buffer acquisition and release also published ownership through protected-call copy-out boundaries that could lose recovery authority under abort.

        Solution: Add bounded generation-stamped buffer pool reservations

        Add controlled reservation claims and authorized release tokens, exact reservation provenance on buffers and capabilities, total acquisition statuses, nonwrapping generations, pending-release reissue, and permanent exhaustion. Publish and clear actual ownership tokens inside protected actions, retain abort-safe cleanup guards, document lock and lifecycle rules, and cover failure boundaries, provenance, finalization, status precedence, lifetime rejection, and production hook elision.

      4. a4ab6d4b
        Problem: Context publication cannot move domain capabilities without nesting protected locks

        A remoting context must publish a reserved header and an ordinary payload as one abort-deferred ownership transition. The validated buffer operations re-enter the domain gate, so calling them while the context registry is protected would invert the lock boundary and leave no safe compound commit point.

        Solution: Add prevalidated direct capability commit moves

        Add provider-only limited ownership moves whose bodies contain only same-subtype field transfers and source clearing. Document the caller-owned validation and publication cut, cover heterogeneous pool provenance, tags, bytes, rejection, and abort behavior, and make the root suite fail closed on any unreviewed helper instruction or retained test hook.

      5. f387f8ec
        Problem: Production hook checks reject the disabled buffer hook package

        The disabled test-hook variant necessarily contributes its package elaboration and literal Enabled symbols to the production archive. The behavioral suite matches the package prefix broadly, so a clean production build fails before the repository can verify the new buffer-domain boundary.

        Solution: Match only executable buffer test seams

        Restrict the archive classifier to the arm, consume, note, and live hook operations plus the imported disabled sentinels. This keeps surviving test behavior detectable without treating the inert disabled package metadata as production test code.

      6. c9125bed
        Problem: Buffer domain API fails strict documentation verification

        The new domain catalogue, sentinels, acquisition results, reservation overloads, and private controlled-operation helpers lack complete GNATdoc annotations. Strict API generation therefore rejects the reviewed dependency series and cannot publish its public contract.

        Solution: Complete buffer domain API annotations

        Document every new public entity and result literal, describe each reservation overload formal, and exclude private implementation helpers while documenting their formals as required by GNATdoc. Format the specification with the owning Flyology project settings.

      7. 5c3d43c4
        Problem: Buffer acquisition status docs overstate reservation state

        The generated API describes Reservation_Not_Active as never published even though a previously published exact generation can later become inactive. It also attributes the bounded claim capacity to a reservation although ordinary unreserved acquisitions share the same pool claim bound.

        Solution: Describe status outcomes by current pool state

        Define Reservation_Not_Active in terms of the exact generation currently being inactive and attribute Claim_Limit_Reached to the pool claim capacity. The wording now matches the implemented and tested status paths.

      8. 810f1088
        Merge pull request #83 from flyology-ada/codex/remoting-buffer-domain-publish

        Add abort-safe heterogeneous buffer domains for remoting

    2. 810f1088 updated to 3859f412index ba75376c

      2 source commits

      1. 84b425b1
        Problem: External consumers do not verify buffer-domain publication

        The out-of-tree consumer does not reference the buffer-domain packages. A stale exact-version Alire lock can therefore supply a pre-domain Flyology source tree while the consumer still builds, leaving the published dependency surface unverified.

        Solution: Compile the buffer-domain API out of tree

        Make the external consumer import Domains and Domains.Drivers, acquire and release a domain-owned buffer, and call the driver diagnostic so the two package specifications and bodies must be packaged, compiled, and linked.

      2. 3859f412
        Merge pull request #84 from flyology-ada/codex/buffer-domain-external-consumer

        Verify buffer-domain API from an external consumer

    Compare source revisions
    Development update

    flyology_debug 0.1.1-dev

    2 updates: 243833e6 through 3859f412

    Bounded in-memory tracing and gauges for Ada

    Manifest fields
    origin
    Show all 2 updates
    1. 243833e6 updated to 810f1088index 36533e23

      8 source commits

      1. 86f831cc
        Problem: Buffer slots can reenter the free pool at their final generation

        A slot whose nonwrapping generation reaches its maximum is released back into the free stack. Its next acquisition fails after the pool has already removed it, corrupting availability and potentially leaving waiters with inconsistent accounting. The remoting buffer-domain work depends on generation-safe capability reuse.

        Solution: Retire slots after their final published generation

        Preflight generation exhaustion before mutating allocation state, omit final-generation slots from the free stack on release, document permanent retirement, and add a statically elided test seam that exercises near-wrap behavior. The regression covers surviving capacity, complete retirement, nonblocking and timed acquisition, coverage integration, and production hook-symbol elision.

      2. 06bbc9c0
        Problem: Runtime-selected buffer pools cannot carry ownership without stored pool access

        Remoting sessions need to choose among heterogeneous buffer pools while moving payload ownership through definite transport capabilities. A pool-bound buffer alone either exposes an access value across the driver boundary or loses the lifetime, domain, and exception-atomicity guarantees needed for zero-copy delivery.

        Solution: Add domain-bound heterogeneous buffer capabilities

        Introduce an immutable buffer-domain catalogue with opaque pool references and access-free driver capabilities. Ownership transfers use abort-deferred protected commits, domain-bound public owners retain compile-time lifetime checks, and all storage access validates the supplied domain. Add wrong-domain, zero-copy, finalization, rollback, hook-elision, and compile-negative lifetime coverage.

      3. 50b84004
        Problem: Remoting header pools cannot be reserved across abort-safe session cleanup

        A remoting session needs exclusive ownership of one heterogeneous buffer pool while messages are in flight, but the existing domain admitted only ordinary acquisitions. It had no bounded reservation claims, generation-safe delayed release, or authority token for acknowledging a retired session after its final context-state cut. Base buffer acquisition and release also published ownership through protected-call copy-out boundaries that could lose recovery authority under abort.

        Solution: Add bounded generation-stamped buffer pool reservations

        Add controlled reservation claims and authorized release tokens, exact reservation provenance on buffers and capabilities, total acquisition statuses, nonwrapping generations, pending-release reissue, and permanent exhaustion. Publish and clear actual ownership tokens inside protected actions, retain abort-safe cleanup guards, document lock and lifecycle rules, and cover failure boundaries, provenance, finalization, status precedence, lifetime rejection, and production hook elision.

      4. a4ab6d4b
        Problem: Context publication cannot move domain capabilities without nesting protected locks

        A remoting context must publish a reserved header and an ordinary payload as one abort-deferred ownership transition. The validated buffer operations re-enter the domain gate, so calling them while the context registry is protected would invert the lock boundary and leave no safe compound commit point.

        Solution: Add prevalidated direct capability commit moves

        Add provider-only limited ownership moves whose bodies contain only same-subtype field transfers and source clearing. Document the caller-owned validation and publication cut, cover heterogeneous pool provenance, tags, bytes, rejection, and abort behavior, and make the root suite fail closed on any unreviewed helper instruction or retained test hook.

      5. f387f8ec
        Problem: Production hook checks reject the disabled buffer hook package

        The disabled test-hook variant necessarily contributes its package elaboration and literal Enabled symbols to the production archive. The behavioral suite matches the package prefix broadly, so a clean production build fails before the repository can verify the new buffer-domain boundary.

        Solution: Match only executable buffer test seams

        Restrict the archive classifier to the arm, consume, note, and live hook operations plus the imported disabled sentinels. This keeps surviving test behavior detectable without treating the inert disabled package metadata as production test code.

      6. c9125bed
        Problem: Buffer domain API fails strict documentation verification

        The new domain catalogue, sentinels, acquisition results, reservation overloads, and private controlled-operation helpers lack complete GNATdoc annotations. Strict API generation therefore rejects the reviewed dependency series and cannot publish its public contract.

        Solution: Complete buffer domain API annotations

        Document every new public entity and result literal, describe each reservation overload formal, and exclude private implementation helpers while documenting their formals as required by GNATdoc. Format the specification with the owning Flyology project settings.

      7. 5c3d43c4
        Problem: Buffer acquisition status docs overstate reservation state

        The generated API describes Reservation_Not_Active as never published even though a previously published exact generation can later become inactive. It also attributes the bounded claim capacity to a reservation although ordinary unreserved acquisitions share the same pool claim bound.

        Solution: Describe status outcomes by current pool state

        Define Reservation_Not_Active in terms of the exact generation currently being inactive and attribute Claim_Limit_Reached to the pool claim capacity. The wording now matches the implemented and tested status paths.

      8. 810f1088
        Merge pull request #83 from flyology-ada/codex/remoting-buffer-domain-publish

        Add abort-safe heterogeneous buffer domains for remoting

    2. 810f1088 updated to 3859f412index ba75376c

      2 source commits

      1. 84b425b1
        Problem: External consumers do not verify buffer-domain publication

        The out-of-tree consumer does not reference the buffer-domain packages. A stale exact-version Alire lock can therefore supply a pre-domain Flyology source tree while the consumer still builds, leaving the published dependency surface unverified.

        Solution: Compile the buffer-domain API out of tree

        Make the external consumer import Domains and Domains.Drivers, acquire and release a domain-owned buffer, and call the driver diagnostic so the two package specifications and bodies must be packaged, compiled, and linked.

      2. 3859f412
        Merge pull request #84 from flyology-ada/codex/buffer-domain-external-consumer

        Verify buffer-domain API from an external consumer

    Compare source revisions
    Development update

    flyology_http 0.1.3-dev

    2 updates: a65f24f4 through b5cd966d

    HTTP client and server library for Flyology tasks

    Manifest fields
    origin
    Show all 2 updates
    1. a65f24f4 updated to 537edbc5index 519c45e4

      3 source commits

      1. f1e65c3d
        Problem: Scoped safe reads expose silently closed pooled H1 sockets

        A server can return a complete response without Connection: close and then silently close the reusable HTTP/1 transport. The next public bounded-buffer GET or HEAD fails at response-head parsing even though the synchronous adapter already performs guarded one-shot stale recovery. This prevents object-storage reconciliation after a conclusive conditional response.

        Solution: Extend guarded stale recovery to complete-body buffer exchanges

        Allow public buffer exchanges to use the existing safe-method, no-source, no-response-byte, reused-transport retry path. Add a deterministic native/lightweight established-child regression that models the complete 412 followed by a dropped GET and replacement connection, and record the executable scenario in the maintained corpus.

      2. 1cded286
        Problem: Nested Alire tests inherit outer compiler selections

        The HTTP test action invokes IRI and QUIC as nested Alire projects. After the development index selected a newer compiler, exported GNAT and GPRbuild prefixes from the outer solve contaminated the nested solve, and the QUIC lane maintained a separate incomplete unset list.

        Solution: Centralize nested toolchain environment isolation

        Clear Flyology, compiler, GPRbuild, and project-path prefixes in the shared nested-test helper, route both IRI and QUIC through it, and extend the action-context regression to cover the toolchain variables.

      3. 537edbc5
        Merge pull request #39 from flyology-ada/codex/scoped-h1-stale-reuse

        Recover scoped safe reads from silently stale H1 leases

    2. 537edbc5 updated to b5cd966dindex e812215c

      3 source commits

      1. 22d8ee67
        Problem: Composable HTTP calls live in parallel Scoped namespaces

        Scoped describes an operation's limited lifetime and ownership discipline, not the provider that performs it. Keeping client and server operation forms in child namespaces makes callers learn two API trees for one state machine, obscures synchronous parity, and encourages downstream wrappers and documentation drift.

        Solution: Colocate composable overloads with their providers

        Move the limited constructors, same-name established initiators, operation state accessors, and typed Finish overloads directly into Flyology.HTTP.Client and Flyology.HTTP.Server. Remove both Scoped namespaces without aliases, migrate every executable caller, and retain the existing ownership, certainty, cancellation, drain, deadline, protocol, and guarded stale-H1 behavior.

      2. 17a403e5
        Problem: HTTP guidance still presents composability as an execution namespace

        The corpus vocabulary, differential tools, generated expectations, architecture notes, and website guides still name Scoped as a parallel API style. That language would teach the removed namespace and leave provider ownership hard to discover after the intentional development-line source break.

        Solution: Document provider-centric composable operations

        Rename corpus execution styles to composable buffer and sink forms, regenerate the Ada oracle, and update conformance and differential tooling. Revise the guides and architecture to place root constructors, established initiation, and typed Finish beside synchronous provider calls while preserving scoped lifetime as an operation semantic.

      3. b5cd966d
        Merge pull request #40 from flyology-ada/codex/flatten-composable-http-api

        Colocate composable HTTP operations with providers

    Compare source revisions
    Development update

    flyology_iri 0.1.1-dev

    2 updates: a65f24f4 through b5cd966d

    Allocation-conscious URI, IRI, and URL reference parser

    Manifest fields
    origin
    Show all 2 updates
    1. a65f24f4 updated to 537edbc5index 519c45e4

      3 source commits

      1. f1e65c3d
        Problem: Scoped safe reads expose silently closed pooled H1 sockets

        A server can return a complete response without Connection: close and then silently close the reusable HTTP/1 transport. The next public bounded-buffer GET or HEAD fails at response-head parsing even though the synchronous adapter already performs guarded one-shot stale recovery. This prevents object-storage reconciliation after a conclusive conditional response.

        Solution: Extend guarded stale recovery to complete-body buffer exchanges

        Allow public buffer exchanges to use the existing safe-method, no-source, no-response-byte, reused-transport retry path. Add a deterministic native/lightweight established-child regression that models the complete 412 followed by a dropped GET and replacement connection, and record the executable scenario in the maintained corpus.

      2. 1cded286
        Problem: Nested Alire tests inherit outer compiler selections

        The HTTP test action invokes IRI and QUIC as nested Alire projects. After the development index selected a newer compiler, exported GNAT and GPRbuild prefixes from the outer solve contaminated the nested solve, and the QUIC lane maintained a separate incomplete unset list.

        Solution: Centralize nested toolchain environment isolation

        Clear Flyology, compiler, GPRbuild, and project-path prefixes in the shared nested-test helper, route both IRI and QUIC through it, and extend the action-context regression to cover the toolchain variables.

      3. 537edbc5
        Merge pull request #39 from flyology-ada/codex/scoped-h1-stale-reuse

        Recover scoped safe reads from silently stale H1 leases

    2. 537edbc5 updated to b5cd966dindex e812215c

      3 source commits

      1. 22d8ee67
        Problem: Composable HTTP calls live in parallel Scoped namespaces

        Scoped describes an operation's limited lifetime and ownership discipline, not the provider that performs it. Keeping client and server operation forms in child namespaces makes callers learn two API trees for one state machine, obscures synchronous parity, and encourages downstream wrappers and documentation drift.

        Solution: Colocate composable overloads with their providers

        Move the limited constructors, same-name established initiators, operation state accessors, and typed Finish overloads directly into Flyology.HTTP.Client and Flyology.HTTP.Server. Remove both Scoped namespaces without aliases, migrate every executable caller, and retain the existing ownership, certainty, cancellation, drain, deadline, protocol, and guarded stale-H1 behavior.

      2. 17a403e5
        Problem: HTTP guidance still presents composability as an execution namespace

        The corpus vocabulary, differential tools, generated expectations, architecture notes, and website guides still name Scoped as a parallel API style. That language would teach the removed namespace and leave provider ownership hard to discover after the intentional development-line source break.

        Solution: Document provider-centric composable operations

        Rename corpus execution styles to composable buffer and sink forms, regenerate the Ada oracle, and update conformance and differential tooling. Revise the guides and architecture to place root constructors, established initiation, and typed Finish beside synchronous provider calls while preserving scoped lifetime as an operation semantic.

      3. b5cd966d
        Merge pull request #40 from flyology-ada/codex/flatten-composable-http-api

        Colocate composable HTTP operations with providers

    Compare source revisions
    Development update

    flyology_numa 0.1.0-dev

    2 updates: 243833e6 through 3859f412

    Memory-node topology reporting for Ada

    Manifest fields
    origin
    Show all 2 updates
    1. 243833e6 updated to 810f1088index 36533e23

      8 source commits

      1. 86f831cc
        Problem: Buffer slots can reenter the free pool at their final generation

        A slot whose nonwrapping generation reaches its maximum is released back into the free stack. Its next acquisition fails after the pool has already removed it, corrupting availability and potentially leaving waiters with inconsistent accounting. The remoting buffer-domain work depends on generation-safe capability reuse.

        Solution: Retire slots after their final published generation

        Preflight generation exhaustion before mutating allocation state, omit final-generation slots from the free stack on release, document permanent retirement, and add a statically elided test seam that exercises near-wrap behavior. The regression covers surviving capacity, complete retirement, nonblocking and timed acquisition, coverage integration, and production hook-symbol elision.

      2. 06bbc9c0
        Problem: Runtime-selected buffer pools cannot carry ownership without stored pool access

        Remoting sessions need to choose among heterogeneous buffer pools while moving payload ownership through definite transport capabilities. A pool-bound buffer alone either exposes an access value across the driver boundary or loses the lifetime, domain, and exception-atomicity guarantees needed for zero-copy delivery.

        Solution: Add domain-bound heterogeneous buffer capabilities

        Introduce an immutable buffer-domain catalogue with opaque pool references and access-free driver capabilities. Ownership transfers use abort-deferred protected commits, domain-bound public owners retain compile-time lifetime checks, and all storage access validates the supplied domain. Add wrong-domain, zero-copy, finalization, rollback, hook-elision, and compile-negative lifetime coverage.

      3. 50b84004
        Problem: Remoting header pools cannot be reserved across abort-safe session cleanup

        A remoting session needs exclusive ownership of one heterogeneous buffer pool while messages are in flight, but the existing domain admitted only ordinary acquisitions. It had no bounded reservation claims, generation-safe delayed release, or authority token for acknowledging a retired session after its final context-state cut. Base buffer acquisition and release also published ownership through protected-call copy-out boundaries that could lose recovery authority under abort.

        Solution: Add bounded generation-stamped buffer pool reservations

        Add controlled reservation claims and authorized release tokens, exact reservation provenance on buffers and capabilities, total acquisition statuses, nonwrapping generations, pending-release reissue, and permanent exhaustion. Publish and clear actual ownership tokens inside protected actions, retain abort-safe cleanup guards, document lock and lifecycle rules, and cover failure boundaries, provenance, finalization, status precedence, lifetime rejection, and production hook elision.

      4. a4ab6d4b
        Problem: Context publication cannot move domain capabilities without nesting protected locks

        A remoting context must publish a reserved header and an ordinary payload as one abort-deferred ownership transition. The validated buffer operations re-enter the domain gate, so calling them while the context registry is protected would invert the lock boundary and leave no safe compound commit point.

        Solution: Add prevalidated direct capability commit moves

        Add provider-only limited ownership moves whose bodies contain only same-subtype field transfers and source clearing. Document the caller-owned validation and publication cut, cover heterogeneous pool provenance, tags, bytes, rejection, and abort behavior, and make the root suite fail closed on any unreviewed helper instruction or retained test hook.

      5. f387f8ec
        Problem: Production hook checks reject the disabled buffer hook package

        The disabled test-hook variant necessarily contributes its package elaboration and literal Enabled symbols to the production archive. The behavioral suite matches the package prefix broadly, so a clean production build fails before the repository can verify the new buffer-domain boundary.

        Solution: Match only executable buffer test seams

        Restrict the archive classifier to the arm, consume, note, and live hook operations plus the imported disabled sentinels. This keeps surviving test behavior detectable without treating the inert disabled package metadata as production test code.

      6. c9125bed
        Problem: Buffer domain API fails strict documentation verification

        The new domain catalogue, sentinels, acquisition results, reservation overloads, and private controlled-operation helpers lack complete GNATdoc annotations. Strict API generation therefore rejects the reviewed dependency series and cannot publish its public contract.

        Solution: Complete buffer domain API annotations

        Document every new public entity and result literal, describe each reservation overload formal, and exclude private implementation helpers while documenting their formals as required by GNATdoc. Format the specification with the owning Flyology project settings.

      7. 5c3d43c4
        Problem: Buffer acquisition status docs overstate reservation state

        The generated API describes Reservation_Not_Active as never published even though a previously published exact generation can later become inactive. It also attributes the bounded claim capacity to a reservation although ordinary unreserved acquisitions share the same pool claim bound.

        Solution: Describe status outcomes by current pool state

        Define Reservation_Not_Active in terms of the exact generation currently being inactive and attribute Claim_Limit_Reached to the pool claim capacity. The wording now matches the implemented and tested status paths.

      8. 810f1088
        Merge pull request #83 from flyology-ada/codex/remoting-buffer-domain-publish

        Add abort-safe heterogeneous buffer domains for remoting

    2. 810f1088 updated to 3859f412index ba75376c

      2 source commits

      1. 84b425b1
        Problem: External consumers do not verify buffer-domain publication

        The out-of-tree consumer does not reference the buffer-domain packages. A stale exact-version Alire lock can therefore supply a pre-domain Flyology source tree while the consumer still builds, leaving the published dependency surface unverified.

        Solution: Compile the buffer-domain API out of tree

        Make the external consumer import Domains and Domains.Drivers, acquire and release a domain-owned buffer, and call the driver diagnostic so the two package specifications and bodies must be packaged, compiled, and linked.

      2. 3859f412
        Merge pull request #84 from flyology-ada/codex/buffer-domain-external-consumer

        Verify buffer-domain API from an external consumer

    Compare source revisions
    Development update

    flyology_quic 0.1.3-dev

    2 updates: a65f24f4 through b5cd966d

    Ada-native QUIC transport for Flyology tasks

    Manifest fields
    origin
    Show all 2 updates
    1. a65f24f4 updated to 537edbc5index 519c45e4

      3 source commits

      1. f1e65c3d
        Problem: Scoped safe reads expose silently closed pooled H1 sockets

        A server can return a complete response without Connection: close and then silently close the reusable HTTP/1 transport. The next public bounded-buffer GET or HEAD fails at response-head parsing even though the synchronous adapter already performs guarded one-shot stale recovery. This prevents object-storage reconciliation after a conclusive conditional response.

        Solution: Extend guarded stale recovery to complete-body buffer exchanges

        Allow public buffer exchanges to use the existing safe-method, no-source, no-response-byte, reused-transport retry path. Add a deterministic native/lightweight established-child regression that models the complete 412 followed by a dropped GET and replacement connection, and record the executable scenario in the maintained corpus.

      2. 1cded286
        Problem: Nested Alire tests inherit outer compiler selections

        The HTTP test action invokes IRI and QUIC as nested Alire projects. After the development index selected a newer compiler, exported GNAT and GPRbuild prefixes from the outer solve contaminated the nested solve, and the QUIC lane maintained a separate incomplete unset list.

        Solution: Centralize nested toolchain environment isolation

        Clear Flyology, compiler, GPRbuild, and project-path prefixes in the shared nested-test helper, route both IRI and QUIC through it, and extend the action-context regression to cover the toolchain variables.

      3. 537edbc5
        Merge pull request #39 from flyology-ada/codex/scoped-h1-stale-reuse

        Recover scoped safe reads from silently stale H1 leases

    2. 537edbc5 updated to b5cd966dindex e812215c

      3 source commits

      1. 22d8ee67
        Problem: Composable HTTP calls live in parallel Scoped namespaces

        Scoped describes an operation's limited lifetime and ownership discipline, not the provider that performs it. Keeping client and server operation forms in child namespaces makes callers learn two API trees for one state machine, obscures synchronous parity, and encourages downstream wrappers and documentation drift.

        Solution: Colocate composable overloads with their providers

        Move the limited constructors, same-name established initiators, operation state accessors, and typed Finish overloads directly into Flyology.HTTP.Client and Flyology.HTTP.Server. Remove both Scoped namespaces without aliases, migrate every executable caller, and retain the existing ownership, certainty, cancellation, drain, deadline, protocol, and guarded stale-H1 behavior.

      2. 17a403e5
        Problem: HTTP guidance still presents composability as an execution namespace

        The corpus vocabulary, differential tools, generated expectations, architecture notes, and website guides still name Scoped as a parallel API style. That language would teach the removed namespace and leave provider ownership hard to discover after the intentional development-line source break.

        Solution: Document provider-centric composable operations

        Rename corpus execution styles to composable buffer and sink forms, regenerate the Ada oracle, and update conformance and differential tooling. Revise the guides and architecture to place root constructors, established initiation, and typed Finish beside synchronous provider calls while preserving scoped lifetime as an operation semantic.

      3. b5cd966d
        Merge pull request #40 from flyology-ada/codex/flatten-composable-http-api

        Colocate composable HTTP operations with providers

    Compare source revisions
  17. Index flyology_simd 0.1.2-dev

    61a792c6 on GitHub
  18. Advance development source pins

    5db3e48d on GitHub
  19. Advance the Flyology TUI development source pin

    49978181 on GitHub
  20. Development updates

    Development update

    flyology_http 0.1.1-dev

    2 updates: dac7fa90 through 92820c5f

    HTTP client and server library for Flyology tasks

    Manifest fields
    depends-on, origin
    Show all 2 updates
    1. dac7fa90 updated to 92820c5findex 9afc79c3

      46 source commits

      1. 7a4ec6c3
        Problem: Server body accounting narrows S3-scale transfers (#24)

        Request limits, decoded-byte counters, route policy, metrics, and diagnostics use Natural throughout the server stack. Values above the platform Natural range can therefore fail during framing or truncate accounting, while the global 1 MiB protocol ceiling prevents S3-scale streaming even when applications retain nothing.

        Solution: Share one 64-bit-safe body size across client and server

        Introduce Flyology.HTTP.Body_Size and carry it through HTTP/1, HTTP/2, HTTP/3, routing, exchanges, logs, and metrics. Raise the streaming protocol ceiling to the current 50 TB S3 object bound while preserving independent ingress limits and the HTTP/3 profile's existing 1 MiB retained-body cap. Make decimal, hexadecimal, accumulation, and metric arithmetic overflow-safe; add 5 GiB and out-of-range framing regressions; and document the streaming-versus-retention boundary.

      2. ca058efa
        Preserve S3 request fidelity and stream H2/H3 uploads (#25)

        * Problem: S3 request fidelity and streaming stop at protocol boundaries

        Solution: preserve authority, physical headers, and request trailers through every server engine; stream borrowed uploads through bounded HTTP/2 and HTTP/3 flow-control paths; raise bounded target metadata limits; and qualify canonicalization, trailers, and cross-boundary uploads.

        * Problem: streaming backpressure can starve protocol progress

        Solution: make H2 wait predicates fragment-size aware, poll output immediately before sleeping, stop H3 uploads on early final responses, and isolate H3 qualification runtimes. Cover zero progress, overrun, source exceptions, cancellation, deadlines, early finals, reuse, and generated 64 GiB sources in both protocol integrations.

      3. ffe9cb00
        Problem: QUIC has no stable release for current HTTP APIs (#26)

        Solution: release flyology_quic 0.1.1 with a stable Flyology dependency range, validated against the published 0.1.0 implementation.

      4. 5638f1c6Problem: HTTP S3 prerequisites have no stable release (#27)
      5. 80609dd7
        Problem: Released HTTP and QUIC changes are not summarized

        Flyology HTTP and Flyology QUIC 0.1.1 have published tags, but users cannot see the notable changes since 0.1.0 or trace them to their pull requests and commits.

        Solution: Add crate-scoped release changelogs

        Document both release ranges in Keep a Changelog format with version comparisons and source links.

      6. 8279a99d
        Problem: Server streams cannot declare exact response lengths

        Object storage handlers know representation sizes but the server only offers retained responses or unknown-length streams. That forces HTTP/1.1 chunking, prevents correct HEAD metadata, and leaves overruns and underruns unchecked.

        Solution: Add proved fixed-length streaming responses

        Expose 64-bit Content_Length overloads through the raw and application APIs, enforce exact completion across HTTP/1.1, HTTP/2, and HTTP/3, preserve HEAD suppression and unknown-length compatibility, and qualify framing, failures, isolation, backpressure, large logical lengths, proofs, and documentation.

      7. 548a41c8
        Solution: Record fixed-length response streams

        Add the new server API, exact framing and completion guarantees, HEAD behavior, and stream-isolation semantics to the unreleased HTTP changelog.

      8. 8cc0e4c5
        Add exact fixed-length server response streams (#28)

        Expose 64-bit known-length streams across HTTP/1.1, HTTP/2, and HTTP/3 with proved exact accounting, correct HEAD semantics, bounded backpressure, failure isolation, tests, and documentation.

      9. 80e7f6b9fix(http2): accept empty HEAD stream completion
      10. fc54793d
        Merge pull request #29 from flyology-ada/codex/fix-http2-head-completion

        fix(http2): accept empty HEAD stream completion

      11. 4e93366frelease flyology_http 0.1.2
      12. 8f34e73b
        Merge pull request #30 from flyology-ada/codex/release-http-0.1.2

        release flyology_http 0.1.2

      13. 2e356498
        Problem: HTTP parsing waits hide protocol state on the blocking stack

        Request-head input inspection and chunked-body framing combine transport suspension with parser progress. In particular, trailer phase and byte accounting are local to a blocking loop, so a scoped operation cannot suspend and resume without duplicating parser semantics or retaining a helper stack.

        Solution: Factor HTTP input parsing into bounded immediate steps

        Separate request initialization and buffered-input inspection, promote trailer progress into the connection state, and advance body framing one bounded transition at a time. Keep the synchronous entry points driving the same steps, and exercise every header, chunk, terminator, and trailer boundary with one-byte transport fragmentation.

      14. a1b43b16
        Problem: Composable HTTP work lacks a controlled performance baseline

        Changing the request wait path can alter the existing native and lightweight HTTP performance profile. Without an untouched c128 cohort and an explicit foundation pin, later throughput or latency changes cannot be attributed or reproduced.

        Solution: Pin the Flyology operation branch and record baseline evidence

        Track codex/composable-operations through a branch pin that remains easy to advance, and document the exact baseline commits, environment, 16-loop runtime, commands, three-sample throughput and latency distributions, resource controls, noise caveats, and pre-existing nested-suite mismatch.

      15. 8e1b04a5
        Problem: HTTP server waits cannot compose as operations

        The public request-head and streaming-body entry points suspend directly through a class-wide transport. Callers cannot combine them with Flyology timers, gates, cancellation, connection setup, or counted completion waits while preserving connection and borrowed-buffer lifetimes.

        Solution: add bounded scoped HTTP server operations

        Add a public immediate-step transport capability backed by the set-independent connection driver, scoped request-head, body-acceptance, and body-read operations, and retained typed Finish procedures. Share bounded parser transitions with the synchronous API, initialize closure state on every parse path, preserve original failures through cleanup, and cover native and lightweight composition, TLS upgrade, cancellation, failure retention, cleanup, partial I/O, and synchronous parity.

      16. d88e70cb
        Problem: Composable HTTP candidate performance is unqualified

        The controlled c128 baseline has no post-change measurements, so reviewers cannot distinguish steady-state regression from host noise or verify the final success count and latency profile.

        Solution: record the current-pin candidate campaign

        Document the exact Flyology and HTTP revisions, qualification commands, three samples per workload and lane, median throughput and latency, baseline deltas, all-success response count, and the observed run-order noise. Mark the results as current-pin evidence that must be repeated when the foundation revision advances.

      17. fcac4635
        Problem: TLS test adapter no longer matches the controller contract

        The final composable-operations foundation refactors the private TLS descriptor controller around explicit operation states. The HTTP repository's test-only child body still calls the removed acquisition primitives, so its authoritative suite cannot compile against the advanced branch pin.

        Solution: synchronize the TLS test adapter state transitions

        Use Start_Operation, Try_Acquire, Abandon_Operation, and state-aware Release exactly as the foundation test helper does. Preserve the existing Generation and stale-acquisition test behavior without adding any production dependency on the private controller.

      18. 18a9ad70
        Problem: Final composable HTTP performance is unqualified

        The intermediate benchmark covers an earlier Flyology operation-provider revision and ran while unrelated stale compiler probes loaded the host. It cannot qualify the replacement PR #60 head or distinguish a synchronous-path regression from host contention.

        Solution: record the serialized final c128 campaign

        Document fresh suite and GNATdoc validation on exact Flyology 195b228, all three alternating 16-loop and native trials, latency and throughput summaries, HTTP status results, and wrapper resource evidence. State the contention caveat and the supported conclusion that the final candidate preserves the established performance profile.

      19. 8de52f57
        Problem: HTTP still depends on the temporary Flyology branch pin

        Flyology composable operations are merged and published as 0.1.1-dev in the organization index. Keeping the mutable Git branch override bypasses that validated release resolution and leaves the consumer tied to review infrastructure.

        Solution: resolve Flyology from the organization index

        Require flyology 0.1.1-dev and remove the custom Git pin. The resolved release is the merged main commit 159210ca44eff9f636e933195bf176c3500ff60e.

      20. a91e1a77
        Problem: Alire test actions can re-enter HTTP dependency setup

        The manifest test action exports ALIRE and Flyology paths without the private HTTP test marker. The test entry can therefore invoke a nested root build, and its IRI child inherits outer dependency paths into a separate Alire workspace.

        Solution: reuse the active Alire test context

        Recognize the standard action environment before any build decision, export the existing marker, and sanitize outer Flyology paths only for the IRI child workspace. Add a shell regression for action-marker inheritance, child isolation, and unchanged direct invocation.

      21. f4d98b2c
        Problem: Composable HTTP operations lack usage guidance

        The low-level HTTP/1.x server API exposes bounded request-head and body operations, but the website does not explain their transport requirements, lifecycle, composition rules, or ownership limits.

        Solution: Add a bounded operations guide

        Document synchronous versus scoped calls, operation-capable plain and upgraded-TLS transports, slot sizing, typed Finish, body sequencing, waits, gates, cancellation, retained failures, and borrowed lifetimes. Link the guide from the guide index, server guide, and llms.txt.

      22. f4fd9c3e
        Merge pull request #31 from flyology-ada/codex/composable-http-operations

        Add composable HTTP server operations

      23. 6f72c29b
        Problem: QUIC receive windows cannot advance for large HTTP/3 responses

        The application stream reassembler is fixed at the initial receive window and the connection cannot return MAX_STREAM_DATA credit. Whole HTTP/3 responses above 16 KiB therefore stall, and old retransmissions below the consumed base can underflow reassembly offsets.

        Solution: add rolling stream receive credit

        Track consumed stream bases, encode and schedule MAX_STREAM_DATA, preserve final-size and overlap checks across window advances, and cover credit, reuse, overlap, and retired retransmission behavior with policy tests.

      24. f0d630d0
        Problem: HTTP client exchanges block inside duplicate protocol engines

        Object storage and database providers cannot compose admission, upload, response-head, and complete-body work on their completion-set owner stack. The synchronous client uses a separate monolithic path, which duplicates H1/H2/H3 policy and can replay ambiguous conditional mutations.

        Solution: make the composable exchange engine canonical

        Add limited root and established exchange operations for owned buffers and streaming sinks, transactional Unique_Buffer restoration, monotonic admission certainty, typed environmental outcomes, one absolute deadline, owner-driven DNS/connect/TLS/H1/H2/H3 children, multiplexed stream isolation, and cancellation drain. Route synchronous Execute through the same request and response-head engine while preserving its retained-response API and exception semantics.

      25. 3d72adbc
        Problem: client correctness has no uniform executable protocol corpus

        The synchronous and composable APIs need the same deterministic scenarios across H1, H2, and H3, including ambiguity, ownership restoration, blocked sources, cancellation drain, malformed multiplexed responses, and large flow-controlled bodies. Existing protocol tests do not provide one shared golden oracle or complete CI coverage.

        Solution: gate both APIs with a shared client corpus

        Add standards-backed JSON scenarios, checked-in binary and hex fixtures, generated Ada expectations, source and sink fault providers, native/lightweight scoped matrices, h2specd client coverage, aioquic and PycURL differentials, large-body reuse, lost-final-response and no-replay oracles, and required CI execution. Ignore Python bytecode artifacts.

      26. 4b1b91c3
        Problem: the client guide documents only blocking exchange behavior

        Users cannot discover the scoped complete-body operations, ownership restoration, admission certainty, parent composition, readiness bounds, or the fact that synchronous Execute now uses the same canonical protocol engine.

        Solution: document composable client exchanges

        Add a complete buffer and sink workflow, child-operation example, cancellation and ambiguity rules, protocol readiness bounds, task-free multiplexing details, current address iteration behavior, corpus evidence boundaries, and development-version changelog entries.

      27. d60726a8
        Problem: Agent resources lack reproducible package ownership

        Fresh clones need a deterministic way to provision Codex and Claude resources without committed skill symlinks. Repository-specific instruction scopes also need to remain owned and versioned with the code they govern instead of becoming shared policy accidentally.

        Solution: Compose local and shared APM packages

        Package each existing repository scope under agent-packages, pin the validated shared profile at an exact commit, and commit the resolved lockfile and generated Codex guides. Document pinned APM installation and add CI that installs Claude rules and both skill trees, compiles Codex instructions, audits the graph, and checks drift.

      28. 4e5fc625
        Problem: QUIC packet rollback exhausts the owner task stack

        Multi-stream packet validation copies the complete bounded stream table before reassembly. The copy adds roughly a megabyte to the owner task's deepest HTTP/3 receive path, so sustained exchanges can overflow an otherwise bounded Flyology task stack.

        Solution: commit stream reassembly in place after packet validation

        Apply validated stream frames directly and rely on the connection-fatal reassembly-conflict boundary to prevent later reuse. Add a driver-level poison-and-no-reuse regression and explicit SPARK witnesses for the receive-window and stream-table invariants; the complete QUIC policy suite proves all 2,156 checks.

      29. 37b7cbbb
        Problem: sustained client exchanges exhaust owner stack storage

        Synchronous compatibility calls accumulate limited function-return temporaries in long caller scopes, while HTTP/3 keeps large event scratch in exchange and body-reader frames. Retry recursion and protocol cleanup diagnostics add further depth, and the HTTP/2 bounded-body check misclassifies representation lengths on body-forbidden responses.

        Solution: reuse results and persistent protocol scratch

        Add procedural Execute and Read_All overloads that drive the same composable engine, make redirect retries iterative, and retain one serialized HTTP/3 event per pooled connection. Remove the legacy synchronous HTTP/3 body path, preserve causal drain phases, flush queued HTTP/2 shutdown work, and align body-forbidden capacity semantics across protocols. Gate the result with 10,000-exchange HTTP/1.1 and HTTP/2 loops, reduced-stack concurrent 8,000-exchange HTTP/3 clients, scoped HEAD/304 buffer regressions, and the repaired deterministic conformance harness.

      30. 2f8add5d
        Problem: Agents updates require manifest edits

        The shared package is pinned to a full commit in apm.yml, duplicating the
        lockfile and preventing apm update from advancing the reviewed dependency
        without rewriting the manifest.

        Solution: Track agents main through the lockfile

        Declare main as the update channel, refresh the exact lockfile pin, and
        document the explicit update, compilation, and audit workflow.

      31. aba55512
        Problem: Long reuse tests inherit connection age rotation

        The extended H1 and H2 reuse regressions are intended to detect stack growth and slot leaks across 10,000 or more exchanges. On a slow runner, the default total connection age expires during the H2 loop. The client correctly retires that transport, but the single-connection independent peer exits and the test misreports the expected rotation as a client failure. Its truncated peer log also hides the terminal request count.

        Solution: Isolate reuse stress from pool age policy

        Disable total-age rotation only in the long H1 and H2 reuse scenarios, consistent with the existing HTTP/2 soak qualification. Keep rotation under the separate deterministic pool-policy tests. Report both ends and aggregate counts from a failed HTTP/2 peer trace so future long-run failures retain useful evidence.

      32. 7daf0b4a
        Problem: Consumer agents omit the required review cycle

        The locked shared package graph predates the findings-driven review rule, so
        Codex and Claude in this repository do not yet require architectural decisions
        and implementation changes to close P0 and P1 findings or explicitly dispose
        of P2 findings before completion.

        Solution: Adopt the shared review-cycle package

        Advance the exact agents lock to the reviewed shared commit and regenerate
        Codex instructions so both clients receive the same remediation and repeat-
        review requirements.

      33. ef6c8d9c
        Problem: Consumer constants audits lose approved value authority

        The locked shared skill reports hard-coded value decisions but does not require
        their durable authority to be recorded beside Ada declarations. Future changes
        can therefore mistake protocol mandates, derived arithmetic, or test capacities
        for arbitrary production policy.

        Solution: Adopt source-adjacent authority documentation

        Advance the exact shared agents lock to the reviewed constants skill. The
        updated portable workflow preserves consequential choices and their stable
        authority in comments while excluding harmless literals from comment noise.

      34. 8a527902
        Problem: HTTP/2 client resets malformed-frame connections

        The composable and synchronous HTTP/2 client rejects a malformed frame from its header before consuming a bounded declared payload. On Linux, closing the socket with those peer bytes unread can replace the queued GOAWAY with a TCP reset, so h2spec cannot observe the required protocol error. Invalid frame lengths also use the generic protocol error instead of FRAME_SIZE_ERROR.

        Solution: Drain bounded malformed frames before protocol failure

        Wait for and consume the declared payload when the complete malformed frame fits the fixed input buffer, matching the server-side defensive path. Select FRAME_SIZE_ERROR for excessive or invalid frame lengths and retain PROTOCOL_ERROR for other invalid headers.

      35. 6e03ebce
        Problem: Consumer locks omit new shared review skills (#37)

        Repositories using the shared agents package remain pinned before the crate-spinout workflow and the refined constants-audit triage. Fresh sessions therefore cannot discover those reviewed capabilities.

        Solution: Refresh the shared agents lock

        Advance every shared package entry to the green agents main revision. The manifest keeps its main update channel while the lock preserves the exact commit and content hashes for reproducible Codex and Claude installs.

      36. 882e2440
        Problem: HTTP/2 GOAWAY can be replaced by TCP reset

        After a peer protocol violation, the owner-stack pump writes GOAWAY and immediately releases the connection lease. Linux can turn that close into a TCP reset while peer input is still arriving, so h2spec cannot observe the required error on semantic CONTINUATION violations. Consuming malformed frame payloads alone does not cover these validly framed protocol errors.

        Solution: Drain protocol-error closes compositionally

        Retain the pump and transport lease after GOAWAY, discard one bounded receive chunk per owner-stack drive, and finish on peer close or a one-second monotonic cleanup deadline capped by the request deadline. Readiness and the cleanup timer remain on the existing operation slot, and normal exchanges are unchanged.

      37. 41471605
        Problem: HTTP/3 reuse stress inherits server age rotation

        The 8,000-exchange HTTP/3 regression is intended to keep one connection alive while crossing stream-table and flow-control credit boundaries. Its test server still has a 20-second total connection age, so a loaded host retires the peer around exchange 5,000 to 7,000 and reports a timeout unrelated to stack or credit reuse.

        Solution: Isolate HTTP/3 reuse stress from age policy

        Disable total-age rotation only for the long-lived HTTP/3 fixture, matching the existing H1 and H2 reuse stress setup. Deterministic pool-policy tests continue to cover connection-age rotation.

      38. 5f23f559
        Problem: Same-flight TLS errors can escape QUIC rejection

        A client can append a forbidden TLS message such as KeyUpdate after Finished in one Handshake CRYPTO range. The server accepts Finished and publishes Connected before checking the trailing message, so rejection depends on a later Handshake packet and h3spec can observe a successful connection.

        Solution: Reject complete trailing Handshake messages before connection publication

        Inspect the already-reassembled CRYPTO bytes immediately after Finished validation and emit the unexpected_message crypto close before HANDSHAKE_DONE. Repeat the exact published h3spec boundary ten times in the qualification gate to keep the scheduling-independent behavior executable.

      39. db0346bb
        Problem: Boundary close checks reject valid peer resets

        The timeout and cancellation fixture expects abandoned HTTP/1 connections to end only with a zero-length receive. macOS can report a typed socket reset when the client closes with unread bytes, causing the raw server to abort and the following exchange to time out even though the client behavior is correct.

        Solution: Accept reset as terminal in the close-only fixture path

        Treat Socket_Error as peer termination only inside Expect_Close while preserving hard failures for request-head reads and response writes. The corrected fixture completes both native and lightweight lanes across 100 consecutive runs.

      40. 262b0c2f
        Problem: HTTP/2 soak stalls hide their terminal wire state

        The qualification runner prints only the first peer events when a concurrent soak fails. A late lost-wakeup or stream-lifecycle stall therefore reports an old request rather than the active streams and event counts needed to distinguish protocol and scheduling failures.

        Solution: Preserve terminal HTTP/2 soak diagnostics

        Record completed request halves and timeout-time active streams in the independent peer. Print bounded first and final event windows plus aggregate request, response, reset, and timeout counts on failure.

      41. 98c0e26f
        Problem: HTTP/2 pump contention can starve a stream

        A just-rescheduled stream can repeatedly reclaim the shared session pump while sibling streams only receive broadcast wakeups. Under concurrent load a sibling can therefore wait through its absolute request deadline even though the transport keeps making progress.

        Solution: Hand off the HTTP/2 pump fairly

        Track bounded waiter state inside the protected session controller and reserve each released pump for the next waiter in round-robin order. Cover the no-cut-in handoff sequence with a deterministic four-stream regression.

      42. 23051ca7
        Problem: Synchronous H2 bodies can bypass protocol close drain

        The synchronous response-body adapter returns as soon as its stream is locally ready or already complete. If an invalid peer frame is received with the final response, that path can release the transport after queuing GOAWAY but before the bounded close drain, replacing the protocol error with TCP reset.

        Solution: Preserve composable drain semantics in the sync adapter

        Keep driving the shared pump through its reported closing-drain budget regardless of local stream readiness, and settle already-complete H2 bodies before returning. The adapter uses the same pump, monotonic request deadline, and bounded one-second protocol-close budget as the composable exchange.

      43. b7fb5474
        Problem: owner-driven h2spec can outrun late invalid frames

        The conformance executable exits after one full exchange. A malicious frame sent just after the response reaches would-block can arrive after the last operation terminalizes, so the peer observes a TCP reset instead of the required HTTP/2 error response. This made closed-stream h2spec cases timing-dependent in CI.

        Solution: give conformance exchanges a bounded settlement probe

        Add a per-client testing-only grace interval that defaults to zero. The synchronous and scoped adapters use their existing owner-stack pump, transport readiness, completion slot, and absolute deadline for one bounded post-response probe. Enable 50 ms only in the h2specd driver and document the qualification boundary.

      44. 153c9c80
        Problem: loaded h2spec peers exceed the initial settlement probe

        The 50 ms conformance-only readiness interval can expire before a lightweight-owner peer schedules a CONTINUATION following RST_STREAM. The client then exits and h2spec observes a TCP reset instead of the queued HTTP/2 stream or connection error.

        Solution: widen the bounded conformance probe to 250 ms

        Keep the production default at zero while giving the single-exchange h2specd driver enough owner-stack readiness time under CI load. Document the exact bound; no helper task, protocol path, completion slot, or application latency changes.

      45. 09e95348
        Problem: development manifests imply unreleased version advances

        The composable-client branch declares flyology_http 0.1.3-dev and flyology_quic 0.1.2-dev even though this work is published by advancing the existing 0.1.1-dev sessions without a stable release. The mismatch would force unnecessary index-version bootstrapping and give consumers the wrong session coordinates.

        Solution: keep both active sessions at 0.1.1-dev

        Restore the HTTP and QUIC crate versions and the exact HTTP-to-QUIC development constraint to 0.1.1-dev. Record that this work advances development origins only and creates no stable release tag.

      46. 92820c5f
        Merge pull request #33 from flyology-ada/codex/composable-http-client-async

        Add composable owner-driven HTTP client exchanges

    2. 92820c5f updated to 92820c5findex 5998ae17

    Dependency changes

    • flyology_quic ~0.1.1-dev changed to =0.1.1-dev
    Compare source revisions
    Development update

    flyology_iri 0.1.1-dev

    2 updates: 8f34e73b through a65f24f4

    Allocation-conscious URI, IRI, and URL reference parser

    Manifest fields
    origin
    Show all 2 updates
    1. 8f34e73b updated to 92820c5findex 39035597

      34 source commits

      1. 2e356498
        Problem: HTTP parsing waits hide protocol state on the blocking stack

        Request-head input inspection and chunked-body framing combine transport suspension with parser progress. In particular, trailer phase and byte accounting are local to a blocking loop, so a scoped operation cannot suspend and resume without duplicating parser semantics or retaining a helper stack.

        Solution: Factor HTTP input parsing into bounded immediate steps

        Separate request initialization and buffered-input inspection, promote trailer progress into the connection state, and advance body framing one bounded transition at a time. Keep the synchronous entry points driving the same steps, and exercise every header, chunk, terminator, and trailer boundary with one-byte transport fragmentation.

      2. a1b43b16
        Problem: Composable HTTP work lacks a controlled performance baseline

        Changing the request wait path can alter the existing native and lightweight HTTP performance profile. Without an untouched c128 cohort and an explicit foundation pin, later throughput or latency changes cannot be attributed or reproduced.

        Solution: Pin the Flyology operation branch and record baseline evidence

        Track codex/composable-operations through a branch pin that remains easy to advance, and document the exact baseline commits, environment, 16-loop runtime, commands, three-sample throughput and latency distributions, resource controls, noise caveats, and pre-existing nested-suite mismatch.

      3. 8e1b04a5
        Problem: HTTP server waits cannot compose as operations

        The public request-head and streaming-body entry points suspend directly through a class-wide transport. Callers cannot combine them with Flyology timers, gates, cancellation, connection setup, or counted completion waits while preserving connection and borrowed-buffer lifetimes.

        Solution: add bounded scoped HTTP server operations

        Add a public immediate-step transport capability backed by the set-independent connection driver, scoped request-head, body-acceptance, and body-read operations, and retained typed Finish procedures. Share bounded parser transitions with the synchronous API, initialize closure state on every parse path, preserve original failures through cleanup, and cover native and lightweight composition, TLS upgrade, cancellation, failure retention, cleanup, partial I/O, and synchronous parity.

      4. d88e70cb
        Problem: Composable HTTP candidate performance is unqualified

        The controlled c128 baseline has no post-change measurements, so reviewers cannot distinguish steady-state regression from host noise or verify the final success count and latency profile.

        Solution: record the current-pin candidate campaign

        Document the exact Flyology and HTTP revisions, qualification commands, three samples per workload and lane, median throughput and latency, baseline deltas, all-success response count, and the observed run-order noise. Mark the results as current-pin evidence that must be repeated when the foundation revision advances.

      5. fcac4635
        Problem: TLS test adapter no longer matches the controller contract

        The final composable-operations foundation refactors the private TLS descriptor controller around explicit operation states. The HTTP repository's test-only child body still calls the removed acquisition primitives, so its authoritative suite cannot compile against the advanced branch pin.

        Solution: synchronize the TLS test adapter state transitions

        Use Start_Operation, Try_Acquire, Abandon_Operation, and state-aware Release exactly as the foundation test helper does. Preserve the existing Generation and stale-acquisition test behavior without adding any production dependency on the private controller.

      6. 18a9ad70
        Problem: Final composable HTTP performance is unqualified

        The intermediate benchmark covers an earlier Flyology operation-provider revision and ran while unrelated stale compiler probes loaded the host. It cannot qualify the replacement PR #60 head or distinguish a synchronous-path regression from host contention.

        Solution: record the serialized final c128 campaign

        Document fresh suite and GNATdoc validation on exact Flyology 195b228, all three alternating 16-loop and native trials, latency and throughput summaries, HTTP status results, and wrapper resource evidence. State the contention caveat and the supported conclusion that the final candidate preserves the established performance profile.

      7. 8de52f57
        Problem: HTTP still depends on the temporary Flyology branch pin

        Flyology composable operations are merged and published as 0.1.1-dev in the organization index. Keeping the mutable Git branch override bypasses that validated release resolution and leaves the consumer tied to review infrastructure.

        Solution: resolve Flyology from the organization index

        Require flyology 0.1.1-dev and remove the custom Git pin. The resolved release is the merged main commit 159210ca44eff9f636e933195bf176c3500ff60e.

      8. a91e1a77
        Problem: Alire test actions can re-enter HTTP dependency setup

        The manifest test action exports ALIRE and Flyology paths without the private HTTP test marker. The test entry can therefore invoke a nested root build, and its IRI child inherits outer dependency paths into a separate Alire workspace.

        Solution: reuse the active Alire test context

        Recognize the standard action environment before any build decision, export the existing marker, and sanitize outer Flyology paths only for the IRI child workspace. Add a shell regression for action-marker inheritance, child isolation, and unchanged direct invocation.

      9. f4d98b2c
        Problem: Composable HTTP operations lack usage guidance

        The low-level HTTP/1.x server API exposes bounded request-head and body operations, but the website does not explain their transport requirements, lifecycle, composition rules, or ownership limits.

        Solution: Add a bounded operations guide

        Document synchronous versus scoped calls, operation-capable plain and upgraded-TLS transports, slot sizing, typed Finish, body sequencing, waits, gates, cancellation, retained failures, and borrowed lifetimes. Link the guide from the guide index, server guide, and llms.txt.

      10. f4fd9c3e
        Merge pull request #31 from flyology-ada/codex/composable-http-operations

        Add composable HTTP server operations

      11. 6f72c29b
        Problem: QUIC receive windows cannot advance for large HTTP/3 responses

        The application stream reassembler is fixed at the initial receive window and the connection cannot return MAX_STREAM_DATA credit. Whole HTTP/3 responses above 16 KiB therefore stall, and old retransmissions below the consumed base can underflow reassembly offsets.

        Solution: add rolling stream receive credit

        Track consumed stream bases, encode and schedule MAX_STREAM_DATA, preserve final-size and overlap checks across window advances, and cover credit, reuse, overlap, and retired retransmission behavior with policy tests.

      12. f0d630d0
        Problem: HTTP client exchanges block inside duplicate protocol engines

        Object storage and database providers cannot compose admission, upload, response-head, and complete-body work on their completion-set owner stack. The synchronous client uses a separate monolithic path, which duplicates H1/H2/H3 policy and can replay ambiguous conditional mutations.

        Solution: make the composable exchange engine canonical

        Add limited root and established exchange operations for owned buffers and streaming sinks, transactional Unique_Buffer restoration, monotonic admission certainty, typed environmental outcomes, one absolute deadline, owner-driven DNS/connect/TLS/H1/H2/H3 children, multiplexed stream isolation, and cancellation drain. Route synchronous Execute through the same request and response-head engine while preserving its retained-response API and exception semantics.

      13. 3d72adbc
        Problem: client correctness has no uniform executable protocol corpus

        The synchronous and composable APIs need the same deterministic scenarios across H1, H2, and H3, including ambiguity, ownership restoration, blocked sources, cancellation drain, malformed multiplexed responses, and large flow-controlled bodies. Existing protocol tests do not provide one shared golden oracle or complete CI coverage.

        Solution: gate both APIs with a shared client corpus

        Add standards-backed JSON scenarios, checked-in binary and hex fixtures, generated Ada expectations, source and sink fault providers, native/lightweight scoped matrices, h2specd client coverage, aioquic and PycURL differentials, large-body reuse, lost-final-response and no-replay oracles, and required CI execution. Ignore Python bytecode artifacts.

      14. 4b1b91c3
        Problem: the client guide documents only blocking exchange behavior

        Users cannot discover the scoped complete-body operations, ownership restoration, admission certainty, parent composition, readiness bounds, or the fact that synchronous Execute now uses the same canonical protocol engine.

        Solution: document composable client exchanges

        Add a complete buffer and sink workflow, child-operation example, cancellation and ambiguity rules, protocol readiness bounds, task-free multiplexing details, current address iteration behavior, corpus evidence boundaries, and development-version changelog entries.

      15. d60726a8
        Problem: Agent resources lack reproducible package ownership

        Fresh clones need a deterministic way to provision Codex and Claude resources without committed skill symlinks. Repository-specific instruction scopes also need to remain owned and versioned with the code they govern instead of becoming shared policy accidentally.

        Solution: Compose local and shared APM packages

        Package each existing repository scope under agent-packages, pin the validated shared profile at an exact commit, and commit the resolved lockfile and generated Codex guides. Document pinned APM installation and add CI that installs Claude rules and both skill trees, compiles Codex instructions, audits the graph, and checks drift.

      16. 4e5fc625
        Problem: QUIC packet rollback exhausts the owner task stack

        Multi-stream packet validation copies the complete bounded stream table before reassembly. The copy adds roughly a megabyte to the owner task's deepest HTTP/3 receive path, so sustained exchanges can overflow an otherwise bounded Flyology task stack.

        Solution: commit stream reassembly in place after packet validation

        Apply validated stream frames directly and rely on the connection-fatal reassembly-conflict boundary to prevent later reuse. Add a driver-level poison-and-no-reuse regression and explicit SPARK witnesses for the receive-window and stream-table invariants; the complete QUIC policy suite proves all 2,156 checks.

      17. 37b7cbbb
        Problem: sustained client exchanges exhaust owner stack storage

        Synchronous compatibility calls accumulate limited function-return temporaries in long caller scopes, while HTTP/3 keeps large event scratch in exchange and body-reader frames. Retry recursion and protocol cleanup diagnostics add further depth, and the HTTP/2 bounded-body check misclassifies representation lengths on body-forbidden responses.

        Solution: reuse results and persistent protocol scratch

        Add procedural Execute and Read_All overloads that drive the same composable engine, make redirect retries iterative, and retain one serialized HTTP/3 event per pooled connection. Remove the legacy synchronous HTTP/3 body path, preserve causal drain phases, flush queued HTTP/2 shutdown work, and align body-forbidden capacity semantics across protocols. Gate the result with 10,000-exchange HTTP/1.1 and HTTP/2 loops, reduced-stack concurrent 8,000-exchange HTTP/3 clients, scoped HEAD/304 buffer regressions, and the repaired deterministic conformance harness.

      18. 2f8add5d
        Problem: Agents updates require manifest edits

        The shared package is pinned to a full commit in apm.yml, duplicating the
        lockfile and preventing apm update from advancing the reviewed dependency
        without rewriting the manifest.

        Solution: Track agents main through the lockfile

        Declare main as the update channel, refresh the exact lockfile pin, and
        document the explicit update, compilation, and audit workflow.

      19. aba55512
        Problem: Long reuse tests inherit connection age rotation

        The extended H1 and H2 reuse regressions are intended to detect stack growth and slot leaks across 10,000 or more exchanges. On a slow runner, the default total connection age expires during the H2 loop. The client correctly retires that transport, but the single-connection independent peer exits and the test misreports the expected rotation as a client failure. Its truncated peer log also hides the terminal request count.

        Solution: Isolate reuse stress from pool age policy

        Disable total-age rotation only in the long H1 and H2 reuse scenarios, consistent with the existing HTTP/2 soak qualification. Keep rotation under the separate deterministic pool-policy tests. Report both ends and aggregate counts from a failed HTTP/2 peer trace so future long-run failures retain useful evidence.

      20. 7daf0b4a
        Problem: Consumer agents omit the required review cycle

        The locked shared package graph predates the findings-driven review rule, so
        Codex and Claude in this repository do not yet require architectural decisions
        and implementation changes to close P0 and P1 findings or explicitly dispose
        of P2 findings before completion.

        Solution: Adopt the shared review-cycle package

        Advance the exact agents lock to the reviewed shared commit and regenerate
        Codex instructions so both clients receive the same remediation and repeat-
        review requirements.

      21. ef6c8d9c
        Problem: Consumer constants audits lose approved value authority

        The locked shared skill reports hard-coded value decisions but does not require
        their durable authority to be recorded beside Ada declarations. Future changes
        can therefore mistake protocol mandates, derived arithmetic, or test capacities
        for arbitrary production policy.

        Solution: Adopt source-adjacent authority documentation

        Advance the exact shared agents lock to the reviewed constants skill. The
        updated portable workflow preserves consequential choices and their stable
        authority in comments while excluding harmless literals from comment noise.

      22. 8a527902
        Problem: HTTP/2 client resets malformed-frame connections

        The composable and synchronous HTTP/2 client rejects a malformed frame from its header before consuming a bounded declared payload. On Linux, closing the socket with those peer bytes unread can replace the queued GOAWAY with a TCP reset, so h2spec cannot observe the required protocol error. Invalid frame lengths also use the generic protocol error instead of FRAME_SIZE_ERROR.

        Solution: Drain bounded malformed frames before protocol failure

        Wait for and consume the declared payload when the complete malformed frame fits the fixed input buffer, matching the server-side defensive path. Select FRAME_SIZE_ERROR for excessive or invalid frame lengths and retain PROTOCOL_ERROR for other invalid headers.

      23. 6e03ebce
        Problem: Consumer locks omit new shared review skills (#37)

        Repositories using the shared agents package remain pinned before the crate-spinout workflow and the refined constants-audit triage. Fresh sessions therefore cannot discover those reviewed capabilities.

        Solution: Refresh the shared agents lock

        Advance every shared package entry to the green agents main revision. The manifest keeps its main update channel while the lock preserves the exact commit and content hashes for reproducible Codex and Claude installs.

      24. 882e2440
        Problem: HTTP/2 GOAWAY can be replaced by TCP reset

        After a peer protocol violation, the owner-stack pump writes GOAWAY and immediately releases the connection lease. Linux can turn that close into a TCP reset while peer input is still arriving, so h2spec cannot observe the required error on semantic CONTINUATION violations. Consuming malformed frame payloads alone does not cover these validly framed protocol errors.

        Solution: Drain protocol-error closes compositionally

        Retain the pump and transport lease after GOAWAY, discard one bounded receive chunk per owner-stack drive, and finish on peer close or a one-second monotonic cleanup deadline capped by the request deadline. Readiness and the cleanup timer remain on the existing operation slot, and normal exchanges are unchanged.

      25. 41471605
        Problem: HTTP/3 reuse stress inherits server age rotation

        The 8,000-exchange HTTP/3 regression is intended to keep one connection alive while crossing stream-table and flow-control credit boundaries. Its test server still has a 20-second total connection age, so a loaded host retires the peer around exchange 5,000 to 7,000 and reports a timeout unrelated to stack or credit reuse.

        Solution: Isolate HTTP/3 reuse stress from age policy

        Disable total-age rotation only for the long-lived HTTP/3 fixture, matching the existing H1 and H2 reuse stress setup. Deterministic pool-policy tests continue to cover connection-age rotation.

      26. 5f23f559
        Problem: Same-flight TLS errors can escape QUIC rejection

        A client can append a forbidden TLS message such as KeyUpdate after Finished in one Handshake CRYPTO range. The server accepts Finished and publishes Connected before checking the trailing message, so rejection depends on a later Handshake packet and h3spec can observe a successful connection.

        Solution: Reject complete trailing Handshake messages before connection publication

        Inspect the already-reassembled CRYPTO bytes immediately after Finished validation and emit the unexpected_message crypto close before HANDSHAKE_DONE. Repeat the exact published h3spec boundary ten times in the qualification gate to keep the scheduling-independent behavior executable.

      27. db0346bb
        Problem: Boundary close checks reject valid peer resets

        The timeout and cancellation fixture expects abandoned HTTP/1 connections to end only with a zero-length receive. macOS can report a typed socket reset when the client closes with unread bytes, causing the raw server to abort and the following exchange to time out even though the client behavior is correct.

        Solution: Accept reset as terminal in the close-only fixture path

        Treat Socket_Error as peer termination only inside Expect_Close while preserving hard failures for request-head reads and response writes. The corrected fixture completes both native and lightweight lanes across 100 consecutive runs.

      28. 262b0c2f
        Problem: HTTP/2 soak stalls hide their terminal wire state

        The qualification runner prints only the first peer events when a concurrent soak fails. A late lost-wakeup or stream-lifecycle stall therefore reports an old request rather than the active streams and event counts needed to distinguish protocol and scheduling failures.

        Solution: Preserve terminal HTTP/2 soak diagnostics

        Record completed request halves and timeout-time active streams in the independent peer. Print bounded first and final event windows plus aggregate request, response, reset, and timeout counts on failure.

      29. 98c0e26f
        Problem: HTTP/2 pump contention can starve a stream

        A just-rescheduled stream can repeatedly reclaim the shared session pump while sibling streams only receive broadcast wakeups. Under concurrent load a sibling can therefore wait through its absolute request deadline even though the transport keeps making progress.

        Solution: Hand off the HTTP/2 pump fairly

        Track bounded waiter state inside the protected session controller and reserve each released pump for the next waiter in round-robin order. Cover the no-cut-in handoff sequence with a deterministic four-stream regression.

      30. 23051ca7
        Problem: Synchronous H2 bodies can bypass protocol close drain

        The synchronous response-body adapter returns as soon as its stream is locally ready or already complete. If an invalid peer frame is received with the final response, that path can release the transport after queuing GOAWAY but before the bounded close drain, replacing the protocol error with TCP reset.

        Solution: Preserve composable drain semantics in the sync adapter

        Keep driving the shared pump through its reported closing-drain budget regardless of local stream readiness, and settle already-complete H2 bodies before returning. The adapter uses the same pump, monotonic request deadline, and bounded one-second protocol-close budget as the composable exchange.

      31. b7fb5474
        Problem: owner-driven h2spec can outrun late invalid frames

        The conformance executable exits after one full exchange. A malicious frame sent just after the response reaches would-block can arrive after the last operation terminalizes, so the peer observes a TCP reset instead of the required HTTP/2 error response. This made closed-stream h2spec cases timing-dependent in CI.

        Solution: give conformance exchanges a bounded settlement probe

        Add a per-client testing-only grace interval that defaults to zero. The synchronous and scoped adapters use their existing owner-stack pump, transport readiness, completion slot, and absolute deadline for one bounded post-response probe. Enable 50 ms only in the h2specd driver and document the qualification boundary.

      32. 153c9c80
        Problem: loaded h2spec peers exceed the initial settlement probe

        The 50 ms conformance-only readiness interval can expire before a lightweight-owner peer schedules a CONTINUATION following RST_STREAM. The client then exits and h2spec observes a TCP reset instead of the queued HTTP/2 stream or connection error.

        Solution: widen the bounded conformance probe to 250 ms

        Keep the production default at zero while giving the single-exchange h2specd driver enough owner-stack readiness time under CI load. Document the exact bound; no helper task, protocol path, completion slot, or application latency changes.

      33. 09e95348
        Problem: development manifests imply unreleased version advances

        The composable-client branch declares flyology_http 0.1.3-dev and flyology_quic 0.1.2-dev even though this work is published by advancing the existing 0.1.1-dev sessions without a stable release. The mismatch would force unnecessary index-version bootstrapping and give consumers the wrong session coordinates.

        Solution: keep both active sessions at 0.1.1-dev

        Restore the HTTP and QUIC crate versions and the exact HTTP-to-QUIC development constraint to 0.1.1-dev. Record that this work advances development origins only and creates no stable release tag.

      34. 92820c5f
        Merge pull request #33 from flyology-ada/codex/composable-http-client-async

        Add composable owner-driven HTTP client exchanges

    2. 92820c5f updated to a65f24f4index 2dcc8dd6

      3 source commits

      1. 2444df84
        Problem: stable releases supersede the active development channel

        HTTP and QUIC still identify their development sessions as 0.1.1-dev. Stable HTTP 0.1.2 and stable QUIC 0.1.1 retire those entries under the Alire index policy, so merged work cannot be published through the development channel and consumers must retain source pins.

        Solution: open a refreshable lockstep 0.1.3-dev channel

        Advance both indexed crate manifests to 0.1.3-dev, keep the HTTP dependency on QUIC exact at the matching development version, and record that this is a development rollover without stable tags.

      2. 686094b1
        Problem: scoped H2 conformance can close before a late violation

        A peer can reset the active stream and immediately send a connection-level violation. The scoped lightweight exchange may finish cancellation and let a short-lived conformance client close between those frames, so h2spec observes TCP RST instead of the required HTTP/2 error handling.

        Solution: retain the configured settlement probe through cancellation

        When the explicit test-only HTTP/2 settlement grace is nonzero, perform one bounded owner-stack read probe before releasing a cancelled stream. Preserve the zero-duration production default, clear the probe state at terminal cancellation, and document the conformance fix.

      3. a65f24f4
        Merge pull request #38 from flyology-ada/codex/http-0.1.2-dev-rollover

        Open the HTTP and QUIC 0.1.3-dev channel

    Compare source revisions
  21. publish the lockstep 0.1.3-dev manifests

    b1dea203 on GitHub
  22. Advance development source pins

    57e28b32 on GitHub
  23. align the active HTTP repository pins

    9afc79c3 on GitHub
  24. Development updates

    Development update

    flyology 0.1.1-dev

    3 updates: ef6841e7 through 417e48ad

    Experimental GNAT runtime extension for native and lightweight Ada tasks

    Manifest fields
    origin
    Show all 3 updates
    1. ef6841e7 updated to 4ec71932index 73e6c1b5

      7 source commits

      1. c9ccf71b
        Problem: Running servers cannot change generations without losing continuity

        Flyology lacks a generation protocol, listener-capability handoff, and coordinated canary lifecycle for replacing a running server with a changed executable. Operators cannot prepare, admit, promote, cancel, drain, fence, or reverse generations through one reviewed ownership model.

        Solution: Add supervised process-generation upgrades and executable guide

        Implement the Ada-owned coordinator and agent protocol, narrow descriptor and bootstrap handoff mechanisms, lifecycle policy, ABI and behavioral checks, and a mechanically extracted two-artifact website guide that exercises promotion and cancellation.

      2. 1fb1025e
        Problem: The upgrade guide does not identify the demo service

        Readers can follow coordinator calls without knowing what behavior changes between the two artifacts or what the verification request proves.

        Solution: Explain the example server and its observable cutover

        Describe the one-byte request/reply behavior, the distinct generation replies, and how promotion and cancellation assertions relate to new connections.

      3. 5ec82af6
        Merge pull request #61 from flyology-ada/codex/process-upgrades

        Add supervised process-generation upgrades

      4. 270984a3
        Problem: Benchmark CI failures hide their local test log

        The standalone flyology_bench Alire action captures command output in alire/alr_test_local.log. Hosted failures currently retain only Alire’s generic wrapper, so maintainers cannot identify which redirected smoke executable or assertion failed.

        Solution: Surface benchmark test diagnostics on failure

        Print the tail of the captured Alire log while preserving the original status, and label the two redirected smoke executables so the retained log names the active command. Successful test output remains unchanged apart from the command labels.

      5. 0081ba78
        Problem: Benchmark smoke counter overflows on fast hosts

        The flyology_bench smoke fixture accumulates every calibrated operation in a Natural. Fast x86-64 runners can execute more than Natural Last operations across the suite, raising Constraint_Error before the runtime-specific tests begin.

        Solution: Use a modular 64-bit operation counter

        Store the volatile sink and scheduler-probe value directly as Interfaces.Unsigned_64. The counter now retains the intended observable work signal without a checked 32-bit accumulation limit.

      6. 04ff6dcd
        Add direct managed client connections (#70)

        * Problem: Managed clients require raw socket adoption boilerplate

        Composable protocol clients need a managed Flyology connection before they can use the public connection driver, but callers must create and connect a raw socket and then transfer it through Take. This obscures the admission, deadline, cancellation, and cleanup boundary.

        Solution: Add a direct managed connection path

        Add Connections.Connect to reserve admission, create and connect the endpoint-family socket under one deadline, and atomically adopt it with existing guards. Cover both lanes, failure cleanup, TLS and driver composition, and document raw and managed client choices.

        * Problem: The managed connection test iterates a platform type

        Execution_Model is discrete on Darwin but an access type on Linux, so iterating its subtype prevents the new smoke test from compiling on a supported platform. The Darwin loop also repeats the configured project default rather than naming the two lanes under test.

        Solution: Run the two execution lanes explicitly

        Move the scenarios into Run_All and invoke it once for Lightweight_Task and once for Native_Task. This preserves the intended parity coverage without platform-dependent subtype iteration or a redundant default-lane pass.

      7. 4ec71932
        Add scoped managed connection construction (#72)

        * Problem: Managed connection setup cannot join completion sets

        * Problem: Managed connect lacks a selective-wait regression

        The scoped construction tests use Wait_All, so they do not directly prove that a managed connect remains visible as one parent result while its hidden child is excluded from a heterogeneous success gate.

        Solution: exercise managed connect with a timer success gate

        Run the gate in both execution models, transfer the winning connection through typed Finish, cancel the timer sibling, and assert peer-close and admission cleanup.

    2. 4ec71932 updated to c6b1bffcindex 980bb9e5

      47 source commits

      1. 12eb5e12Problem: Benchmark confidence policy is fixed
      2. a9567c3bProblem: Bootstrap settings permit pathological analysis
      3. 2a4f4862
        Problem: Benchmark documentation links target a stale API anchor

        The statistical-policy changes alter the generated GNATdoc identity for Compare_Independent. The benchmarking guide and comparison journal retain the previous fragment, so the Pages link checker rejects the site built for PR #62.

        Solution: Point both links at the regenerated entity anchor

        Update the two deep links to the fragment emitted for Compare_Independent by the current flyology_bench API documentation.

      4. 98f7201a
        Problem: Statistical smoke retains a stale counter type

        Current main widens the benchmark smoke counter to Unsigned_64 so fast hosts cannot overflow it. The statistical-policy layer snapshots that counter as Natural, making the rebased stack fail compilation before any benchmark runs.

        Solution: Match the snapshot to the widened counter

        Store the pre-execution snapshot as Interfaces.Unsigned_64 so assignment and comparison remain type-correct across the counter full range.

      5. 1c7a45e4
        Problem: Equal-time smoke faults on noisy calibration ratios

        The statistical smoke compares two live timing medians against a fixed fourfold ratio. Very fast operations can calibrate into dissimilar observed slices under scheduler and timer noise even though both slices are valid, causing intermittent Program_Error before the benchmark API is exercised further.

        Solution: Validate timed-slice validity instead of proximity

        Require both retained median batch durations to be positive. The smoke still verifies that equal-time comparison produced timed samples and separately verifies the configured batching policy, without treating host timing noise as a correctness failure.

      6. f628b406
        Problem: Interference smoke requires observable host load

        The retake and pause checks require a helper process to cross a tick-based host CPU counter window. Runner scheduling can leave no actionable contaminated window, so the test faults even though the harness reports a coherent observation.

        Solution: Validate responses only when the host observes them

        Use tick-sized interference samples and windows, retain bounded response and sample-count checks, and require pause counters, elapsed time, and retaken samples to agree. A run with no actionable external window is now a valid integration outcome.

      7. 713783bfAdd extensible benchmark metrics and manual timing
      8. cb1c0c6bFix custom metric comparison reporting
      9. 1be316cbHarden manual timing adapters
      10. 340086a7Preserve missing custom probe failures
      11. cc7a3938
        Problem: Custom metrics bypass configured statistics

        Custom metric summaries and comparisons retain fixed bootstrap sizes and 95 percent interval tails after configurable statistical policy is introduced. Their additional intervals also remain outside the aggregate bootstrap-work ceiling.

        Solution: Apply the result's statistical policy to custom metrics

        Size custom bootstrap distributions from the configured resample count, derive their interval tails from the configured confidence level, and include every registered custom metric in bootstrap-work validation.

      12. e9100447Add saved baseline regression gates
      13. 4c4382afFix baseline gate compatibility and reporting
      14. 8aba46e3Prove baseline regression arithmetic bounds
      15. fedeeb77
        Problem: Baseline gates discard statistical policy

        The regression gate fixes every independent comparison at 95 percent confidence and 2,000 resamples even when callers use another benchmark policy. This also leaves the gate's bootstrap work outside the shared safety ceiling.

        Solution: Make gate statistics explicit and bounded

        Add source-compatible defaulted confidence and resample parameters to gate evaluation, propagate them through comparison and result metadata, validate aggregate bootstrap work, and cover non-default policy retention.

      16. 0b9f10be
        Problem: Baseline equivalence smoke depends on live timing noise

        The saved and current inputs reuse one live measurement, but the independent bootstrap resamples them separately. Scheduler outliers can widen the interval beyond the fixed threshold, causing valid inconclusive results to fail the benchmark test intermittently on CI and locally.

        Solution: Exercise gate policy with deterministic samples

        Add a test-only child helper that constructs a private measurement from a fixed mildly dispersed vector. Use that measurement for equivalence, boundary, inconclusive, and reporter coverage while retaining live measurements for collection and coarse improvement/regression smoke checks.

      17. de70616e
        Problem: Benchmark floating proofs exhaust level-one budgets

        The Ratio and Time_Change postconditions leave nonlinear floating-point bounds in combined prover searches. GNATprove 16.1.0 can reach its one-second level-one prover limit on Ubuntu CI even though repeated proofs may pass locally.

        Solution: Split the floating bounds into stable proof obligations

        State Ratio bounds directly in its postcondition and retain the exact Time_Change arithmetic while asserting each difficult bound in its matching branch. The final postcondition becomes a cheap control-flow merge without raising the global proof level or changing returned values.

      18. 8b189587
        Problem: Benchmark proofs still exceed the CI prover limit

        Ubuntu GNATprove 16.1.0 still reaches the default one-second limit on the remaining Ratio monotonicity proof and the faster Time_Change bound. Further structural splits relocate the same floating-point search without reducing it.

        Solution: Give only the benchmark proof a two-second timeout

        Keep level 1 and every other proof invocation unchanged while extending the already-isolated baseline math proof budget. Record the focused budget and its rationale in the benchmark proof status.

      19. 7406db05
        Problem: Benchmark proof still exceeds its focused budget

        Ubuntu GNATprove 16.1.0 can still exhaust the isolated two-second timeout on the Ratio lower-bound postcondition after the structural proof split. This leaves otherwise valid stack heads intermittently red.

        Solution: Widen only the benchmark proof timeout

        Increase the Baseline_Math timeout to five seconds while retaining level 1 and every other proof budget. Update the proof-status record to match the executable invocation.

      20. 739287caAdd benchmark parameter sweeps and scaling analysis
      21. ce31f2e2Fix sweep availability and scaling metadata
      22. 449eff4bFix sweep availability and display reporting
      23. dbf06156Fix sweep failure and scaling states
      24. 03d277e6Fix exact sweep boundaries and reporting
      25. ac1a8781Test final sweep budget stop semantics
      26. cee1d4abAdd explicit flyology_bench suite runner
      27. 5334042aFix benchmark suite reporting and execution
      28. e1433649
        Problem: Suite context changes reporter profiles

        Adding a defaulted context formal lets ordinary calls compile but breaks source uses that depend on the exact legacy reporter profile, including access attributes, renamings, and generic actuals. Ada also forbids overloading generic units.

        Solution: Preserve legacy profiles beside contextual reporters

        Restore exact pre-suite reporter signatures as forwarding entry points, expose contextual overloads for ordinary procedures and distinctly named contextual multi-way generics, update suite bindings, and compile-check access and renaming compatibility.

      29. b5f078d4
        Problem: Suite rejection status has no baseline gate

        The suite aggregate reserves a regression-rejected outcome but registered measurements cannot evaluate a saved baseline. Users must duplicate execution and reporting logic outside the runner, and the suite cannot propagate a gate failure to its final status.

        Solution: Add explicit read-only gated registrations

        Let ordinary cases opt into a saved-baseline policy, evaluate it with the suite's effective confidence, resample, and seed settings after collection, report the gate in every output style, and give rejection precedence in the aggregate without creating or updating artifacts.

      30. a062b019
        Problem: Benchmark documentation filter is overbroad

        The GNATdoc workaround accepts any generic-formal warning from several benchmark units, so a newly undocumented public formal can pass documentation verification unnoticed.

        Solution: Match only known GNATdoc false positives

        Split the benchmark-unit filters and enumerate the exact root, reporter, sweep, and suite generic formal names that GNATdoc 26 misclassifies while continuing to reject every other warning.

      31. 962e5a48
        Problem: Benchmark smoke failures omit their Ada call chain

        Hosted-runner memory faults currently end with only a runtime Storage_Error location. The local action log cannot identify which benchmark or reporter frame raised it, so platform-only failures are not actionable from CI evidence.

        Solution: Capture symbolic test exception tracebacks

        Build test mains with debug information and GNAT symbolic exception traceback support. On smoke failure, emit the complete exception occurrence to standard error before preserving the original unhandled failure.

      32. a637cc13
        Problem: Suite smoke closes an active runner output view

        The reporting-failure scenario closes the caller's Ada.Text_IO file from inside a benchmark callback while Execute still holds and uses that file. GNAT platforms may retain a dangling internal file view, so the subsequent CSV header write can raise erroneous-memory-access instead of the Status_Error the test expects.

        Solution: Keep runner streams valid for the execution lifetime

        Remove the invalid cross-callback close scenario and document that Output and Progress must remain open and must not be reset or closed until Execute returns. Existing callback-failure tests continue to cover runner failure accounting without invoking dangling Text_IO behavior.

      33. 6f2cf34cAdd isolated benchmark worker processes
      34. 8a195f6dHarden isolated benchmark worker containment
      35. 2fb07b32Harden benchmark worker ownership validation
      36. c537aff4Harden benchmark worker result validation
      37. afb23533Protect benchmark worker environment metadata
      38. a29271b3Harden benchmark worker metadata validation
      39. 3d0ce30a
        Problem: Worker mode duplicates suite case dispatch

        Fresh-process executables must currently reconstruct case selection beside the suite registry, so the parent identity and worker callback can drift. Readiness and result return are also repeated in each worker main.

        Solution: Execute worker requests through the suite registry

        Validate the requested identity and result kind against an exact registration, rebuild worker-local configuration, announce readiness, invoke Execute_One, and return the matching protocol result. Update the maintained example to use this shared dispatch path.

      40. c9c465f1
        Merge pull request #67 from flyology-ada/codex/bench-06-process-workers

        Add fresh-process benchmark workers

      41. 6b7273a1
        Problem: Ada formatting policy is inconsistent across the repository

        Flyology and its standalone subcrates lack one enforced line-length and encoding policy. GNAT-preprocessed units also require a documented path that preserves every conditional branch.

        Solution: Standardize Ada formatting at 110 columns

        Configure each owning project for 110-column UTF-8 GNATformat output and matching compiler checks, align runtime compilation, document the preprocessing workflow, and reformat all tracked handwritten Ada sources.

      42. ccf08b27
        Problem: Ada preprocessing blocks uniform formatting of test seams

        GNATformat skips Ada units containing preprocessing directives, while the former test-hook switches made production code generation depend on a preprocessing pass. The repository also lacked an isolated regression proving that every hook selection is correct and that disabled calls disappear at all supported optimization levels.

        Solution: Select hook packages through GPR source directories

        Replace Ada directives with documented enabled and disabled private package variants, guard hook references with literal constants, and expose imported sentinels for missed guards. Add a dedicated cross-platform CI job that checks all 256 selections, optimization modes, and production archives without adding the exhaustive pass to the ordinary test suite.

      43. edf9d8c0
        Problem: Formatted sources fail Linux and Pages validation

        GNAT's runtime style checker rejects a formatter-shifted comment in the Linux file engine, preventing runtime assembly. GNATformat also separates three leading GNATdoc @exclude tags from their declarations, causing the Pages build to report those internal adapter instances as undocumented public API.

        Solution: Restore validation-sensitive comment placement

        Place the runtime comment in the GNAT style column, keep each @exclude tag adjacent to its declaration, and document the GNATformat exception in the agent guide.

      44. 2987d103
        Problem: multiplexed protocol operations cannot compose outbound wakeups

        An owner-stack connection protocol can arm hidden transport and lifecycle readiness through a Capability, but it cannot include the opaque Outbound_Wakeup used by concurrent stream publishers. Multiplexed clients therefore lack one bounded wait set and would need a helper pump or exposed descriptor.

        Solution: compose outbound publication with transport arming

        Add the narrow Arm_Transport overload that arms the required hidden transport direction, outbound wake source, and lifecycle sources on one outer operation. Consume already-pending notifications before rescheduling to prevent stale-signal spin, preserve independent deadlines, and cover pending, later-signal, reuse, TLS, deadline, native, and lightweight paths.

      45. 3815cc9d
        Problem: scoped socket children cannot compose lifecycle wake sources

        Established stream and datagram operations can block on transport readiness, but most scoped stream calls and Receive_Datagram cannot include caller-owned cancellation or protocol-output descriptors. DNS, HTTP/2, and HTTP/3 parents therefore cannot wake hidden socket work without a helper.

        Solution: add bounded interrupt sets to scoped socket operations

        Add source-compatible Interrupts parameters to scoped stream array operations and datagram receive roots, copy the bounded descriptor set into caller-owned operation storage, and arm it with transport readiness. Retain typed interruption and device failures and cover already-pending and later-signalled datagram interrupts in native and lightweight lanes.

      46. ebf80d6b
        Problem: DNS resolution cannot compose with scoped client operations

        Flyology.IO.DNS exposes only synchronous Resolve calls, so an HTTP parent cannot preserve one owner-stack deadline and cancellation scope while resolving an origin. Wrapping the synchronous resolver would block a lightweight event-loop pthread and cannot participate in Continue_After or completion gates.

        Solution: implement a bounded scoped DNS resolver state machine

        Add reusable resolver configuration snapshots, limited Resolve operations with root and established starts, and typed Finish parity. Drive numeric, localhost, cache, search, family, retry, UDP, TCP fallback, token, deadline, and cancellation paths through hidden scoped socket children, with transactional capacity rollback and complete drain-before-publication tests in both lanes.

      47. c6b1bffc
        Merge pull request #75 from flyology-ada/codex/scoped-dns-resolver

        Add composable scoped DNS resolution

    3. c6b1bffc updated to 417e48adindex f41acb68

      2 source commits

      1. 56a47436
        Problem: Scoped transports cannot compose all readiness sources

        HTTP multiplexing needs one operation to wait on hidden transport, outbound,
        lifecycle, token, and caller-source descriptors. The four-source bound overflows
        H2, and datagram receives cannot express a direction-sensitive caller source
        for H3.

        Solution: Raise readiness capacity and add caller-source arming overloads

        Raise the operation, public I/O, and runtime limits to six interests per
        operation. Add connection and datagram overloads that include one validated,
        caller-borrowed read-or-write descriptor in the existing bounded wait, retain
        the outbound consume-before-reschedule rule, and cover native and lightweight
        readiness, race, deadline, cancellation, and reuse behavior.

      2. 417e48ad
        Compose six scoped transport readiness sources (#76)

        Preserve the reviewed Problem/Solution prerequisite commit and merge it after the complete Linux/macOS, SPARK, TLA+, and Pages matrix passed.

    Compare source revisions
    Development update

    flyology_allocators 0.1.0-dev

    3 updates: ef6841e7 through 417e48ad

    Caller-owned memory allocation algorithms for Ada

    Manifest fields
    origin
    Show all 3 updates
    1. ef6841e7 updated to 4ec71932index 73e6c1b5

      7 source commits

      1. c9ccf71b
        Problem: Running servers cannot change generations without losing continuity

        Flyology lacks a generation protocol, listener-capability handoff, and coordinated canary lifecycle for replacing a running server with a changed executable. Operators cannot prepare, admit, promote, cancel, drain, fence, or reverse generations through one reviewed ownership model.

        Solution: Add supervised process-generation upgrades and executable guide

        Implement the Ada-owned coordinator and agent protocol, narrow descriptor and bootstrap handoff mechanisms, lifecycle policy, ABI and behavioral checks, and a mechanically extracted two-artifact website guide that exercises promotion and cancellation.

      2. 1fb1025e
        Problem: The upgrade guide does not identify the demo service

        Readers can follow coordinator calls without knowing what behavior changes between the two artifacts or what the verification request proves.

        Solution: Explain the example server and its observable cutover

        Describe the one-byte request/reply behavior, the distinct generation replies, and how promotion and cancellation assertions relate to new connections.

      3. 5ec82af6
        Merge pull request #61 from flyology-ada/codex/process-upgrades

        Add supervised process-generation upgrades

      4. 270984a3
        Problem: Benchmark CI failures hide their local test log

        The standalone flyology_bench Alire action captures command output in alire/alr_test_local.log. Hosted failures currently retain only Alire’s generic wrapper, so maintainers cannot identify which redirected smoke executable or assertion failed.

        Solution: Surface benchmark test diagnostics on failure

        Print the tail of the captured Alire log while preserving the original status, and label the two redirected smoke executables so the retained log names the active command. Successful test output remains unchanged apart from the command labels.

      5. 0081ba78
        Problem: Benchmark smoke counter overflows on fast hosts

        The flyology_bench smoke fixture accumulates every calibrated operation in a Natural. Fast x86-64 runners can execute more than Natural Last operations across the suite, raising Constraint_Error before the runtime-specific tests begin.

        Solution: Use a modular 64-bit operation counter

        Store the volatile sink and scheduler-probe value directly as Interfaces.Unsigned_64. The counter now retains the intended observable work signal without a checked 32-bit accumulation limit.

      6. 04ff6dcd
        Add direct managed client connections (#70)

        * Problem: Managed clients require raw socket adoption boilerplate

        Composable protocol clients need a managed Flyology connection before they can use the public connection driver, but callers must create and connect a raw socket and then transfer it through Take. This obscures the admission, deadline, cancellation, and cleanup boundary.

        Solution: Add a direct managed connection path

        Add Connections.Connect to reserve admission, create and connect the endpoint-family socket under one deadline, and atomically adopt it with existing guards. Cover both lanes, failure cleanup, TLS and driver composition, and document raw and managed client choices.

        * Problem: The managed connection test iterates a platform type

        Execution_Model is discrete on Darwin but an access type on Linux, so iterating its subtype prevents the new smoke test from compiling on a supported platform. The Darwin loop also repeats the configured project default rather than naming the two lanes under test.

        Solution: Run the two execution lanes explicitly

        Move the scenarios into Run_All and invoke it once for Lightweight_Task and once for Native_Task. This preserves the intended parity coverage without platform-dependent subtype iteration or a redundant default-lane pass.

      7. 4ec71932
        Add scoped managed connection construction (#72)

        * Problem: Managed connection setup cannot join completion sets

        * Problem: Managed connect lacks a selective-wait regression

        The scoped construction tests use Wait_All, so they do not directly prove that a managed connect remains visible as one parent result while its hidden child is excluded from a heterogeneous success gate.

        Solution: exercise managed connect with a timer success gate

        Run the gate in both execution models, transfer the winning connection through typed Finish, cancel the timer sibling, and assert peer-close and admission cleanup.

    2. 4ec71932 updated to c6b1bffcindex 980bb9e5

      47 source commits

      1. 12eb5e12Problem: Benchmark confidence policy is fixed
      2. a9567c3bProblem: Bootstrap settings permit pathological analysis
      3. 2a4f4862
        Problem: Benchmark documentation links target a stale API anchor

        The statistical-policy changes alter the generated GNATdoc identity for Compare_Independent. The benchmarking guide and comparison journal retain the previous fragment, so the Pages link checker rejects the site built for PR #62.

        Solution: Point both links at the regenerated entity anchor

        Update the two deep links to the fragment emitted for Compare_Independent by the current flyology_bench API documentation.

      4. 98f7201a
        Problem: Statistical smoke retains a stale counter type

        Current main widens the benchmark smoke counter to Unsigned_64 so fast hosts cannot overflow it. The statistical-policy layer snapshots that counter as Natural, making the rebased stack fail compilation before any benchmark runs.

        Solution: Match the snapshot to the widened counter

        Store the pre-execution snapshot as Interfaces.Unsigned_64 so assignment and comparison remain type-correct across the counter full range.

      5. 1c7a45e4
        Problem: Equal-time smoke faults on noisy calibration ratios

        The statistical smoke compares two live timing medians against a fixed fourfold ratio. Very fast operations can calibrate into dissimilar observed slices under scheduler and timer noise even though both slices are valid, causing intermittent Program_Error before the benchmark API is exercised further.

        Solution: Validate timed-slice validity instead of proximity

        Require both retained median batch durations to be positive. The smoke still verifies that equal-time comparison produced timed samples and separately verifies the configured batching policy, without treating host timing noise as a correctness failure.

      6. f628b406
        Problem: Interference smoke requires observable host load

        The retake and pause checks require a helper process to cross a tick-based host CPU counter window. Runner scheduling can leave no actionable contaminated window, so the test faults even though the harness reports a coherent observation.

        Solution: Validate responses only when the host observes them

        Use tick-sized interference samples and windows, retain bounded response and sample-count checks, and require pause counters, elapsed time, and retaken samples to agree. A run with no actionable external window is now a valid integration outcome.

      7. 713783bfAdd extensible benchmark metrics and manual timing
      8. cb1c0c6bFix custom metric comparison reporting
      9. 1be316cbHarden manual timing adapters
      10. 340086a7Preserve missing custom probe failures
      11. cc7a3938
        Problem: Custom metrics bypass configured statistics

        Custom metric summaries and comparisons retain fixed bootstrap sizes and 95 percent interval tails after configurable statistical policy is introduced. Their additional intervals also remain outside the aggregate bootstrap-work ceiling.

        Solution: Apply the result's statistical policy to custom metrics

        Size custom bootstrap distributions from the configured resample count, derive their interval tails from the configured confidence level, and include every registered custom metric in bootstrap-work validation.

      12. e9100447Add saved baseline regression gates
      13. 4c4382afFix baseline gate compatibility and reporting
      14. 8aba46e3Prove baseline regression arithmetic bounds
      15. fedeeb77
        Problem: Baseline gates discard statistical policy

        The regression gate fixes every independent comparison at 95 percent confidence and 2,000 resamples even when callers use another benchmark policy. This also leaves the gate's bootstrap work outside the shared safety ceiling.

        Solution: Make gate statistics explicit and bounded

        Add source-compatible defaulted confidence and resample parameters to gate evaluation, propagate them through comparison and result metadata, validate aggregate bootstrap work, and cover non-default policy retention.

      16. 0b9f10be
        Problem: Baseline equivalence smoke depends on live timing noise

        The saved and current inputs reuse one live measurement, but the independent bootstrap resamples them separately. Scheduler outliers can widen the interval beyond the fixed threshold, causing valid inconclusive results to fail the benchmark test intermittently on CI and locally.

        Solution: Exercise gate policy with deterministic samples

        Add a test-only child helper that constructs a private measurement from a fixed mildly dispersed vector. Use that measurement for equivalence, boundary, inconclusive, and reporter coverage while retaining live measurements for collection and coarse improvement/regression smoke checks.

      17. de70616e
        Problem: Benchmark floating proofs exhaust level-one budgets

        The Ratio and Time_Change postconditions leave nonlinear floating-point bounds in combined prover searches. GNATprove 16.1.0 can reach its one-second level-one prover limit on Ubuntu CI even though repeated proofs may pass locally.

        Solution: Split the floating bounds into stable proof obligations

        State Ratio bounds directly in its postcondition and retain the exact Time_Change arithmetic while asserting each difficult bound in its matching branch. The final postcondition becomes a cheap control-flow merge without raising the global proof level or changing returned values.

      18. 8b189587
        Problem: Benchmark proofs still exceed the CI prover limit

        Ubuntu GNATprove 16.1.0 still reaches the default one-second limit on the remaining Ratio monotonicity proof and the faster Time_Change bound. Further structural splits relocate the same floating-point search without reducing it.

        Solution: Give only the benchmark proof a two-second timeout

        Keep level 1 and every other proof invocation unchanged while extending the already-isolated baseline math proof budget. Record the focused budget and its rationale in the benchmark proof status.

      19. 7406db05
        Problem: Benchmark proof still exceeds its focused budget

        Ubuntu GNATprove 16.1.0 can still exhaust the isolated two-second timeout on the Ratio lower-bound postcondition after the structural proof split. This leaves otherwise valid stack heads intermittently red.

        Solution: Widen only the benchmark proof timeout

        Increase the Baseline_Math timeout to five seconds while retaining level 1 and every other proof budget. Update the proof-status record to match the executable invocation.

      20. 739287caAdd benchmark parameter sweeps and scaling analysis
      21. ce31f2e2Fix sweep availability and scaling metadata
      22. 449eff4bFix sweep availability and display reporting
      23. dbf06156Fix sweep failure and scaling states
      24. 03d277e6Fix exact sweep boundaries and reporting
      25. ac1a8781Test final sweep budget stop semantics
      26. cee1d4abAdd explicit flyology_bench suite runner
      27. 5334042aFix benchmark suite reporting and execution
      28. e1433649
        Problem: Suite context changes reporter profiles

        Adding a defaulted context formal lets ordinary calls compile but breaks source uses that depend on the exact legacy reporter profile, including access attributes, renamings, and generic actuals. Ada also forbids overloading generic units.

        Solution: Preserve legacy profiles beside contextual reporters

        Restore exact pre-suite reporter signatures as forwarding entry points, expose contextual overloads for ordinary procedures and distinctly named contextual multi-way generics, update suite bindings, and compile-check access and renaming compatibility.

      29. b5f078d4
        Problem: Suite rejection status has no baseline gate

        The suite aggregate reserves a regression-rejected outcome but registered measurements cannot evaluate a saved baseline. Users must duplicate execution and reporting logic outside the runner, and the suite cannot propagate a gate failure to its final status.

        Solution: Add explicit read-only gated registrations

        Let ordinary cases opt into a saved-baseline policy, evaluate it with the suite's effective confidence, resample, and seed settings after collection, report the gate in every output style, and give rejection precedence in the aggregate without creating or updating artifacts.

      30. a062b019
        Problem: Benchmark documentation filter is overbroad

        The GNATdoc workaround accepts any generic-formal warning from several benchmark units, so a newly undocumented public formal can pass documentation verification unnoticed.

        Solution: Match only known GNATdoc false positives

        Split the benchmark-unit filters and enumerate the exact root, reporter, sweep, and suite generic formal names that GNATdoc 26 misclassifies while continuing to reject every other warning.

      31. 962e5a48
        Problem: Benchmark smoke failures omit their Ada call chain

        Hosted-runner memory faults currently end with only a runtime Storage_Error location. The local action log cannot identify which benchmark or reporter frame raised it, so platform-only failures are not actionable from CI evidence.

        Solution: Capture symbolic test exception tracebacks

        Build test mains with debug information and GNAT symbolic exception traceback support. On smoke failure, emit the complete exception occurrence to standard error before preserving the original unhandled failure.

      32. a637cc13
        Problem: Suite smoke closes an active runner output view

        The reporting-failure scenario closes the caller's Ada.Text_IO file from inside a benchmark callback while Execute still holds and uses that file. GNAT platforms may retain a dangling internal file view, so the subsequent CSV header write can raise erroneous-memory-access instead of the Status_Error the test expects.

        Solution: Keep runner streams valid for the execution lifetime

        Remove the invalid cross-callback close scenario and document that Output and Progress must remain open and must not be reset or closed until Execute returns. Existing callback-failure tests continue to cover runner failure accounting without invoking dangling Text_IO behavior.

      33. 6f2cf34cAdd isolated benchmark worker processes
      34. 8a195f6dHarden isolated benchmark worker containment
      35. 2fb07b32Harden benchmark worker ownership validation
      36. c537aff4Harden benchmark worker result validation
      37. afb23533Protect benchmark worker environment metadata
      38. a29271b3Harden benchmark worker metadata validation
      39. 3d0ce30a
        Problem: Worker mode duplicates suite case dispatch

        Fresh-process executables must currently reconstruct case selection beside the suite registry, so the parent identity and worker callback can drift. Readiness and result return are also repeated in each worker main.

        Solution: Execute worker requests through the suite registry

        Validate the requested identity and result kind against an exact registration, rebuild worker-local configuration, announce readiness, invoke Execute_One, and return the matching protocol result. Update the maintained example to use this shared dispatch path.

      40. c9c465f1
        Merge pull request #67 from flyology-ada/codex/bench-06-process-workers

        Add fresh-process benchmark workers

      41. 6b7273a1
        Problem: Ada formatting policy is inconsistent across the repository

        Flyology and its standalone subcrates lack one enforced line-length and encoding policy. GNAT-preprocessed units also require a documented path that preserves every conditional branch.

        Solution: Standardize Ada formatting at 110 columns

        Configure each owning project for 110-column UTF-8 GNATformat output and matching compiler checks, align runtime compilation, document the preprocessing workflow, and reformat all tracked handwritten Ada sources.

      42. ccf08b27
        Problem: Ada preprocessing blocks uniform formatting of test seams

        GNATformat skips Ada units containing preprocessing directives, while the former test-hook switches made production code generation depend on a preprocessing pass. The repository also lacked an isolated regression proving that every hook selection is correct and that disabled calls disappear at all supported optimization levels.

        Solution: Select hook packages through GPR source directories

        Replace Ada directives with documented enabled and disabled private package variants, guard hook references with literal constants, and expose imported sentinels for missed guards. Add a dedicated cross-platform CI job that checks all 256 selections, optimization modes, and production archives without adding the exhaustive pass to the ordinary test suite.

      43. edf9d8c0
        Problem: Formatted sources fail Linux and Pages validation

        GNAT's runtime style checker rejects a formatter-shifted comment in the Linux file engine, preventing runtime assembly. GNATformat also separates three leading GNATdoc @exclude tags from their declarations, causing the Pages build to report those internal adapter instances as undocumented public API.

        Solution: Restore validation-sensitive comment placement

        Place the runtime comment in the GNAT style column, keep each @exclude tag adjacent to its declaration, and document the GNATformat exception in the agent guide.

      44. 2987d103
        Problem: multiplexed protocol operations cannot compose outbound wakeups

        An owner-stack connection protocol can arm hidden transport and lifecycle readiness through a Capability, but it cannot include the opaque Outbound_Wakeup used by concurrent stream publishers. Multiplexed clients therefore lack one bounded wait set and would need a helper pump or exposed descriptor.

        Solution: compose outbound publication with transport arming

        Add the narrow Arm_Transport overload that arms the required hidden transport direction, outbound wake source, and lifecycle sources on one outer operation. Consume already-pending notifications before rescheduling to prevent stale-signal spin, preserve independent deadlines, and cover pending, later-signal, reuse, TLS, deadline, native, and lightweight paths.

      45. 3815cc9d
        Problem: scoped socket children cannot compose lifecycle wake sources

        Established stream and datagram operations can block on transport readiness, but most scoped stream calls and Receive_Datagram cannot include caller-owned cancellation or protocol-output descriptors. DNS, HTTP/2, and HTTP/3 parents therefore cannot wake hidden socket work without a helper.

        Solution: add bounded interrupt sets to scoped socket operations

        Add source-compatible Interrupts parameters to scoped stream array operations and datagram receive roots, copy the bounded descriptor set into caller-owned operation storage, and arm it with transport readiness. Retain typed interruption and device failures and cover already-pending and later-signalled datagram interrupts in native and lightweight lanes.

      46. ebf80d6b
        Problem: DNS resolution cannot compose with scoped client operations

        Flyology.IO.DNS exposes only synchronous Resolve calls, so an HTTP parent cannot preserve one owner-stack deadline and cancellation scope while resolving an origin. Wrapping the synchronous resolver would block a lightweight event-loop pthread and cannot participate in Continue_After or completion gates.

        Solution: implement a bounded scoped DNS resolver state machine

        Add reusable resolver configuration snapshots, limited Resolve operations with root and established starts, and typed Finish parity. Drive numeric, localhost, cache, search, family, retry, UDP, TCP fallback, token, deadline, and cancellation paths through hidden scoped socket children, with transactional capacity rollback and complete drain-before-publication tests in both lanes.

      47. c6b1bffc
        Merge pull request #75 from flyology-ada/codex/scoped-dns-resolver

        Add composable scoped DNS resolution

    3. c6b1bffc updated to 417e48adindex f41acb68

      2 source commits

      1. 56a47436
        Problem: Scoped transports cannot compose all readiness sources

        HTTP multiplexing needs one operation to wait on hidden transport, outbound,
        lifecycle, token, and caller-source descriptors. The four-source bound overflows
        H2, and datagram receives cannot express a direction-sensitive caller source
        for H3.

        Solution: Raise readiness capacity and add caller-source arming overloads

        Raise the operation, public I/O, and runtime limits to six interests per
        operation. Add connection and datagram overloads that include one validated,
        caller-borrowed read-or-write descriptor in the existing bounded wait, retain
        the outbound consume-before-reschedule rule, and cover native and lightweight
        readiness, race, deadline, cancellation, and reuse behavior.

      2. 417e48ad
        Compose six scoped transport readiness sources (#76)

        Preserve the reviewed Problem/Solution prerequisite commit and merge it after the complete Linux/macOS, SPARK, TLA+, and Pages matrix passed.

    Compare source revisions
    Development update

    flyology_bench 0.1.1-dev

    3 updates: ef6841e7 through 417e48ad

    Adaptive nanosecond-scale benchmarking for Ada

    Manifest fields
    origin
    Show all 3 updates
    1. ef6841e7 updated to 4ec71932index 73e6c1b5

      7 source commits

      1. c9ccf71b
        Problem: Running servers cannot change generations without losing continuity

        Flyology lacks a generation protocol, listener-capability handoff, and coordinated canary lifecycle for replacing a running server with a changed executable. Operators cannot prepare, admit, promote, cancel, drain, fence, or reverse generations through one reviewed ownership model.

        Solution: Add supervised process-generation upgrades and executable guide

        Implement the Ada-owned coordinator and agent protocol, narrow descriptor and bootstrap handoff mechanisms, lifecycle policy, ABI and behavioral checks, and a mechanically extracted two-artifact website guide that exercises promotion and cancellation.

      2. 1fb1025e
        Problem: The upgrade guide does not identify the demo service

        Readers can follow coordinator calls without knowing what behavior changes between the two artifacts or what the verification request proves.

        Solution: Explain the example server and its observable cutover

        Describe the one-byte request/reply behavior, the distinct generation replies, and how promotion and cancellation assertions relate to new connections.

      3. 5ec82af6
        Merge pull request #61 from flyology-ada/codex/process-upgrades

        Add supervised process-generation upgrades

      4. 270984a3
        Problem: Benchmark CI failures hide their local test log

        The standalone flyology_bench Alire action captures command output in alire/alr_test_local.log. Hosted failures currently retain only Alire’s generic wrapper, so maintainers cannot identify which redirected smoke executable or assertion failed.

        Solution: Surface benchmark test diagnostics on failure

        Print the tail of the captured Alire log while preserving the original status, and label the two redirected smoke executables so the retained log names the active command. Successful test output remains unchanged apart from the command labels.

      5. 0081ba78
        Problem: Benchmark smoke counter overflows on fast hosts

        The flyology_bench smoke fixture accumulates every calibrated operation in a Natural. Fast x86-64 runners can execute more than Natural Last operations across the suite, raising Constraint_Error before the runtime-specific tests begin.

        Solution: Use a modular 64-bit operation counter

        Store the volatile sink and scheduler-probe value directly as Interfaces.Unsigned_64. The counter now retains the intended observable work signal without a checked 32-bit accumulation limit.

      6. 04ff6dcd
        Add direct managed client connections (#70)

        * Problem: Managed clients require raw socket adoption boilerplate

        Composable protocol clients need a managed Flyology connection before they can use the public connection driver, but callers must create and connect a raw socket and then transfer it through Take. This obscures the admission, deadline, cancellation, and cleanup boundary.

        Solution: Add a direct managed connection path

        Add Connections.Connect to reserve admission, create and connect the endpoint-family socket under one deadline, and atomically adopt it with existing guards. Cover both lanes, failure cleanup, TLS and driver composition, and document raw and managed client choices.

        * Problem: The managed connection test iterates a platform type

        Execution_Model is discrete on Darwin but an access type on Linux, so iterating its subtype prevents the new smoke test from compiling on a supported platform. The Darwin loop also repeats the configured project default rather than naming the two lanes under test.

        Solution: Run the two execution lanes explicitly

        Move the scenarios into Run_All and invoke it once for Lightweight_Task and once for Native_Task. This preserves the intended parity coverage without platform-dependent subtype iteration or a redundant default-lane pass.

      7. 4ec71932
        Add scoped managed connection construction (#72)

        * Problem: Managed connection setup cannot join completion sets

        * Problem: Managed connect lacks a selective-wait regression

        The scoped construction tests use Wait_All, so they do not directly prove that a managed connect remains visible as one parent result while its hidden child is excluded from a heterogeneous success gate.

        Solution: exercise managed connect with a timer success gate

        Run the gate in both execution models, transfer the winning connection through typed Finish, cancel the timer sibling, and assert peer-close and admission cleanup.

    2. 4ec71932 updated to c6b1bffcindex 980bb9e5

      47 source commits

      1. 12eb5e12Problem: Benchmark confidence policy is fixed
      2. a9567c3bProblem: Bootstrap settings permit pathological analysis
      3. 2a4f4862
        Problem: Benchmark documentation links target a stale API anchor

        The statistical-policy changes alter the generated GNATdoc identity for Compare_Independent. The benchmarking guide and comparison journal retain the previous fragment, so the Pages link checker rejects the site built for PR #62.

        Solution: Point both links at the regenerated entity anchor

        Update the two deep links to the fragment emitted for Compare_Independent by the current flyology_bench API documentation.

      4. 98f7201a
        Problem: Statistical smoke retains a stale counter type

        Current main widens the benchmark smoke counter to Unsigned_64 so fast hosts cannot overflow it. The statistical-policy layer snapshots that counter as Natural, making the rebased stack fail compilation before any benchmark runs.

        Solution: Match the snapshot to the widened counter

        Store the pre-execution snapshot as Interfaces.Unsigned_64 so assignment and comparison remain type-correct across the counter full range.

      5. 1c7a45e4
        Problem: Equal-time smoke faults on noisy calibration ratios

        The statistical smoke compares two live timing medians against a fixed fourfold ratio. Very fast operations can calibrate into dissimilar observed slices under scheduler and timer noise even though both slices are valid, causing intermittent Program_Error before the benchmark API is exercised further.

        Solution: Validate timed-slice validity instead of proximity

        Require both retained median batch durations to be positive. The smoke still verifies that equal-time comparison produced timed samples and separately verifies the configured batching policy, without treating host timing noise as a correctness failure.

      6. f628b406
        Problem: Interference smoke requires observable host load

        The retake and pause checks require a helper process to cross a tick-based host CPU counter window. Runner scheduling can leave no actionable contaminated window, so the test faults even though the harness reports a coherent observation.

        Solution: Validate responses only when the host observes them

        Use tick-sized interference samples and windows, retain bounded response and sample-count checks, and require pause counters, elapsed time, and retaken samples to agree. A run with no actionable external window is now a valid integration outcome.

      7. 713783bfAdd extensible benchmark metrics and manual timing
      8. cb1c0c6bFix custom metric comparison reporting
      9. 1be316cbHarden manual timing adapters
      10. 340086a7Preserve missing custom probe failures
      11. cc7a3938
        Problem: Custom metrics bypass configured statistics

        Custom metric summaries and comparisons retain fixed bootstrap sizes and 95 percent interval tails after configurable statistical policy is introduced. Their additional intervals also remain outside the aggregate bootstrap-work ceiling.

        Solution: Apply the result's statistical policy to custom metrics

        Size custom bootstrap distributions from the configured resample count, derive their interval tails from the configured confidence level, and include every registered custom metric in bootstrap-work validation.

      12. e9100447Add saved baseline regression gates
      13. 4c4382afFix baseline gate compatibility and reporting
      14. 8aba46e3Prove baseline regression arithmetic bounds
      15. fedeeb77
        Problem: Baseline gates discard statistical policy

        The regression gate fixes every independent comparison at 95 percent confidence and 2,000 resamples even when callers use another benchmark policy. This also leaves the gate's bootstrap work outside the shared safety ceiling.

        Solution: Make gate statistics explicit and bounded

        Add source-compatible defaulted confidence and resample parameters to gate evaluation, propagate them through comparison and result metadata, validate aggregate bootstrap work, and cover non-default policy retention.

      16. 0b9f10be
        Problem: Baseline equivalence smoke depends on live timing noise

        The saved and current inputs reuse one live measurement, but the independent bootstrap resamples them separately. Scheduler outliers can widen the interval beyond the fixed threshold, causing valid inconclusive results to fail the benchmark test intermittently on CI and locally.

        Solution: Exercise gate policy with deterministic samples

        Add a test-only child helper that constructs a private measurement from a fixed mildly dispersed vector. Use that measurement for equivalence, boundary, inconclusive, and reporter coverage while retaining live measurements for collection and coarse improvement/regression smoke checks.

      17. de70616e
        Problem: Benchmark floating proofs exhaust level-one budgets

        The Ratio and Time_Change postconditions leave nonlinear floating-point bounds in combined prover searches. GNATprove 16.1.0 can reach its one-second level-one prover limit on Ubuntu CI even though repeated proofs may pass locally.

        Solution: Split the floating bounds into stable proof obligations

        State Ratio bounds directly in its postcondition and retain the exact Time_Change arithmetic while asserting each difficult bound in its matching branch. The final postcondition becomes a cheap control-flow merge without raising the global proof level or changing returned values.

      18. 8b189587
        Problem: Benchmark proofs still exceed the CI prover limit

        Ubuntu GNATprove 16.1.0 still reaches the default one-second limit on the remaining Ratio monotonicity proof and the faster Time_Change bound. Further structural splits relocate the same floating-point search without reducing it.

        Solution: Give only the benchmark proof a two-second timeout

        Keep level 1 and every other proof invocation unchanged while extending the already-isolated baseline math proof budget. Record the focused budget and its rationale in the benchmark proof status.

      19. 7406db05
        Problem: Benchmark proof still exceeds its focused budget

        Ubuntu GNATprove 16.1.0 can still exhaust the isolated two-second timeout on the Ratio lower-bound postcondition after the structural proof split. This leaves otherwise valid stack heads intermittently red.

        Solution: Widen only the benchmark proof timeout

        Increase the Baseline_Math timeout to five seconds while retaining level 1 and every other proof budget. Update the proof-status record to match the executable invocation.

      20. 739287caAdd benchmark parameter sweeps and scaling analysis
      21. ce31f2e2Fix sweep availability and scaling metadata
      22. 449eff4bFix sweep availability and display reporting
      23. dbf06156Fix sweep failure and scaling states
      24. 03d277e6Fix exact sweep boundaries and reporting
      25. ac1a8781Test final sweep budget stop semantics
      26. cee1d4abAdd explicit flyology_bench suite runner
      27. 5334042aFix benchmark suite reporting and execution
      28. e1433649
        Problem: Suite context changes reporter profiles

        Adding a defaulted context formal lets ordinary calls compile but breaks source uses that depend on the exact legacy reporter profile, including access attributes, renamings, and generic actuals. Ada also forbids overloading generic units.

        Solution: Preserve legacy profiles beside contextual reporters

        Restore exact pre-suite reporter signatures as forwarding entry points, expose contextual overloads for ordinary procedures and distinctly named contextual multi-way generics, update suite bindings, and compile-check access and renaming compatibility.

      29. b5f078d4
        Problem: Suite rejection status has no baseline gate

        The suite aggregate reserves a regression-rejected outcome but registered measurements cannot evaluate a saved baseline. Users must duplicate execution and reporting logic outside the runner, and the suite cannot propagate a gate failure to its final status.

        Solution: Add explicit read-only gated registrations

        Let ordinary cases opt into a saved-baseline policy, evaluate it with the suite's effective confidence, resample, and seed settings after collection, report the gate in every output style, and give rejection precedence in the aggregate without creating or updating artifacts.

      30. a062b019
        Problem: Benchmark documentation filter is overbroad

        The GNATdoc workaround accepts any generic-formal warning from several benchmark units, so a newly undocumented public formal can pass documentation verification unnoticed.

        Solution: Match only known GNATdoc false positives

        Split the benchmark-unit filters and enumerate the exact root, reporter, sweep, and suite generic formal names that GNATdoc 26 misclassifies while continuing to reject every other warning.

      31. 962e5a48
        Problem: Benchmark smoke failures omit their Ada call chain

        Hosted-runner memory faults currently end with only a runtime Storage_Error location. The local action log cannot identify which benchmark or reporter frame raised it, so platform-only failures are not actionable from CI evidence.

        Solution: Capture symbolic test exception tracebacks

        Build test mains with debug information and GNAT symbolic exception traceback support. On smoke failure, emit the complete exception occurrence to standard error before preserving the original unhandled failure.

      32. a637cc13
        Problem: Suite smoke closes an active runner output view

        The reporting-failure scenario closes the caller's Ada.Text_IO file from inside a benchmark callback while Execute still holds and uses that file. GNAT platforms may retain a dangling internal file view, so the subsequent CSV header write can raise erroneous-memory-access instead of the Status_Error the test expects.

        Solution: Keep runner streams valid for the execution lifetime

        Remove the invalid cross-callback close scenario and document that Output and Progress must remain open and must not be reset or closed until Execute returns. Existing callback-failure tests continue to cover runner failure accounting without invoking dangling Text_IO behavior.

      33. 6f2cf34cAdd isolated benchmark worker processes
      34. 8a195f6dHarden isolated benchmark worker containment
      35. 2fb07b32Harden benchmark worker ownership validation
      36. c537aff4Harden benchmark worker result validation
      37. afb23533Protect benchmark worker environment metadata
      38. a29271b3Harden benchmark worker metadata validation
      39. 3d0ce30a
        Problem: Worker mode duplicates suite case dispatch

        Fresh-process executables must currently reconstruct case selection beside the suite registry, so the parent identity and worker callback can drift. Readiness and result return are also repeated in each worker main.

        Solution: Execute worker requests through the suite registry

        Validate the requested identity and result kind against an exact registration, rebuild worker-local configuration, announce readiness, invoke Execute_One, and return the matching protocol result. Update the maintained example to use this shared dispatch path.

      40. c9c465f1
        Merge pull request #67 from flyology-ada/codex/bench-06-process-workers

        Add fresh-process benchmark workers

      41. 6b7273a1
        Problem: Ada formatting policy is inconsistent across the repository

        Flyology and its standalone subcrates lack one enforced line-length and encoding policy. GNAT-preprocessed units also require a documented path that preserves every conditional branch.

        Solution: Standardize Ada formatting at 110 columns

        Configure each owning project for 110-column UTF-8 GNATformat output and matching compiler checks, align runtime compilation, document the preprocessing workflow, and reformat all tracked handwritten Ada sources.

      42. ccf08b27
        Problem: Ada preprocessing blocks uniform formatting of test seams

        GNATformat skips Ada units containing preprocessing directives, while the former test-hook switches made production code generation depend on a preprocessing pass. The repository also lacked an isolated regression proving that every hook selection is correct and that disabled calls disappear at all supported optimization levels.

        Solution: Select hook packages through GPR source directories

        Replace Ada directives with documented enabled and disabled private package variants, guard hook references with literal constants, and expose imported sentinels for missed guards. Add a dedicated cross-platform CI job that checks all 256 selections, optimization modes, and production archives without adding the exhaustive pass to the ordinary test suite.

      43. edf9d8c0
        Problem: Formatted sources fail Linux and Pages validation

        GNAT's runtime style checker rejects a formatter-shifted comment in the Linux file engine, preventing runtime assembly. GNATformat also separates three leading GNATdoc @exclude tags from their declarations, causing the Pages build to report those internal adapter instances as undocumented public API.

        Solution: Restore validation-sensitive comment placement

        Place the runtime comment in the GNAT style column, keep each @exclude tag adjacent to its declaration, and document the GNATformat exception in the agent guide.

      44. 2987d103
        Problem: multiplexed protocol operations cannot compose outbound wakeups

        An owner-stack connection protocol can arm hidden transport and lifecycle readiness through a Capability, but it cannot include the opaque Outbound_Wakeup used by concurrent stream publishers. Multiplexed clients therefore lack one bounded wait set and would need a helper pump or exposed descriptor.

        Solution: compose outbound publication with transport arming

        Add the narrow Arm_Transport overload that arms the required hidden transport direction, outbound wake source, and lifecycle sources on one outer operation. Consume already-pending notifications before rescheduling to prevent stale-signal spin, preserve independent deadlines, and cover pending, later-signal, reuse, TLS, deadline, native, and lightweight paths.

      45. 3815cc9d
        Problem: scoped socket children cannot compose lifecycle wake sources

        Established stream and datagram operations can block on transport readiness, but most scoped stream calls and Receive_Datagram cannot include caller-owned cancellation or protocol-output descriptors. DNS, HTTP/2, and HTTP/3 parents therefore cannot wake hidden socket work without a helper.

        Solution: add bounded interrupt sets to scoped socket operations

        Add source-compatible Interrupts parameters to scoped stream array operations and datagram receive roots, copy the bounded descriptor set into caller-owned operation storage, and arm it with transport readiness. Retain typed interruption and device failures and cover already-pending and later-signalled datagram interrupts in native and lightweight lanes.

      46. ebf80d6b
        Problem: DNS resolution cannot compose with scoped client operations

        Flyology.IO.DNS exposes only synchronous Resolve calls, so an HTTP parent cannot preserve one owner-stack deadline and cancellation scope while resolving an origin. Wrapping the synchronous resolver would block a lightweight event-loop pthread and cannot participate in Continue_After or completion gates.

        Solution: implement a bounded scoped DNS resolver state machine

        Add reusable resolver configuration snapshots, limited Resolve operations with root and established starts, and typed Finish parity. Drive numeric, localhost, cache, search, family, retry, UDP, TCP fallback, token, deadline, and cancellation paths through hidden scoped socket children, with transactional capacity rollback and complete drain-before-publication tests in both lanes.

      47. c6b1bffc
        Merge pull request #75 from flyology-ada/codex/scoped-dns-resolver

        Add composable scoped DNS resolution

    3. c6b1bffc updated to 417e48adindex f41acb68

      2 source commits

      1. 56a47436
        Problem: Scoped transports cannot compose all readiness sources

        HTTP multiplexing needs one operation to wait on hidden transport, outbound,
        lifecycle, token, and caller-source descriptors. The four-source bound overflows
        H2, and datagram receives cannot express a direction-sensitive caller source
        for H3.

        Solution: Raise readiness capacity and add caller-source arming overloads

        Raise the operation, public I/O, and runtime limits to six interests per
        operation. Add connection and datagram overloads that include one validated,
        caller-borrowed read-or-write descriptor in the existing bounded wait, retain
        the outbound consume-before-reschedule rule, and cover native and lightweight
        readiness, race, deadline, cancellation, and reuse behavior.

      2. 417e48ad
        Compose six scoped transport readiness sources (#76)

        Preserve the reviewed Problem/Solution prerequisite commit and merge it after the complete Linux/macOS, SPARK, TLA+, and Pages matrix passed.

    Compare source revisions
    Development update

    flyology_cachelines 0.1.1-dev

    3 updates: ef6841e7 through 417e48ad

    Cache-line-aware storage and cache information for Ada

    Manifest fields
    origin
    Show all 3 updates
    1. ef6841e7 updated to 4ec71932index 73e6c1b5

      7 source commits

      1. c9ccf71b
        Problem: Running servers cannot change generations without losing continuity

        Flyology lacks a generation protocol, listener-capability handoff, and coordinated canary lifecycle for replacing a running server with a changed executable. Operators cannot prepare, admit, promote, cancel, drain, fence, or reverse generations through one reviewed ownership model.

        Solution: Add supervised process-generation upgrades and executable guide

        Implement the Ada-owned coordinator and agent protocol, narrow descriptor and bootstrap handoff mechanisms, lifecycle policy, ABI and behavioral checks, and a mechanically extracted two-artifact website guide that exercises promotion and cancellation.

      2. 1fb1025e
        Problem: The upgrade guide does not identify the demo service

        Readers can follow coordinator calls without knowing what behavior changes between the two artifacts or what the verification request proves.

        Solution: Explain the example server and its observable cutover

        Describe the one-byte request/reply behavior, the distinct generation replies, and how promotion and cancellation assertions relate to new connections.

      3. 5ec82af6
        Merge pull request #61 from flyology-ada/codex/process-upgrades

        Add supervised process-generation upgrades

      4. 270984a3
        Problem: Benchmark CI failures hide their local test log

        The standalone flyology_bench Alire action captures command output in alire/alr_test_local.log. Hosted failures currently retain only Alire’s generic wrapper, so maintainers cannot identify which redirected smoke executable or assertion failed.

        Solution: Surface benchmark test diagnostics on failure

        Print the tail of the captured Alire log while preserving the original status, and label the two redirected smoke executables so the retained log names the active command. Successful test output remains unchanged apart from the command labels.

      5. 0081ba78
        Problem: Benchmark smoke counter overflows on fast hosts

        The flyology_bench smoke fixture accumulates every calibrated operation in a Natural. Fast x86-64 runners can execute more than Natural Last operations across the suite, raising Constraint_Error before the runtime-specific tests begin.

        Solution: Use a modular 64-bit operation counter

        Store the volatile sink and scheduler-probe value directly as Interfaces.Unsigned_64. The counter now retains the intended observable work signal without a checked 32-bit accumulation limit.

      6. 04ff6dcd
        Add direct managed client connections (#70)

        * Problem: Managed clients require raw socket adoption boilerplate

        Composable protocol clients need a managed Flyology connection before they can use the public connection driver, but callers must create and connect a raw socket and then transfer it through Take. This obscures the admission, deadline, cancellation, and cleanup boundary.

        Solution: Add a direct managed connection path

        Add Connections.Connect to reserve admission, create and connect the endpoint-family socket under one deadline, and atomically adopt it with existing guards. Cover both lanes, failure cleanup, TLS and driver composition, and document raw and managed client choices.

        * Problem: The managed connection test iterates a platform type

        Execution_Model is discrete on Darwin but an access type on Linux, so iterating its subtype prevents the new smoke test from compiling on a supported platform. The Darwin loop also repeats the configured project default rather than naming the two lanes under test.

        Solution: Run the two execution lanes explicitly

        Move the scenarios into Run_All and invoke it once for Lightweight_Task and once for Native_Task. This preserves the intended parity coverage without platform-dependent subtype iteration or a redundant default-lane pass.

      7. 4ec71932
        Add scoped managed connection construction (#72)

        * Problem: Managed connection setup cannot join completion sets

        * Problem: Managed connect lacks a selective-wait regression

        The scoped construction tests use Wait_All, so they do not directly prove that a managed connect remains visible as one parent result while its hidden child is excluded from a heterogeneous success gate.

        Solution: exercise managed connect with a timer success gate

        Run the gate in both execution models, transfer the winning connection through typed Finish, cancel the timer sibling, and assert peer-close and admission cleanup.

    2. 4ec71932 updated to c6b1bffcindex 980bb9e5

      47 source commits

      1. 12eb5e12Problem: Benchmark confidence policy is fixed
      2. a9567c3bProblem: Bootstrap settings permit pathological analysis
      3. 2a4f4862
        Problem: Benchmark documentation links target a stale API anchor

        The statistical-policy changes alter the generated GNATdoc identity for Compare_Independent. The benchmarking guide and comparison journal retain the previous fragment, so the Pages link checker rejects the site built for PR #62.

        Solution: Point both links at the regenerated entity anchor

        Update the two deep links to the fragment emitted for Compare_Independent by the current flyology_bench API documentation.

      4. 98f7201a
        Problem: Statistical smoke retains a stale counter type

        Current main widens the benchmark smoke counter to Unsigned_64 so fast hosts cannot overflow it. The statistical-policy layer snapshots that counter as Natural, making the rebased stack fail compilation before any benchmark runs.

        Solution: Match the snapshot to the widened counter

        Store the pre-execution snapshot as Interfaces.Unsigned_64 so assignment and comparison remain type-correct across the counter full range.

      5. 1c7a45e4
        Problem: Equal-time smoke faults on noisy calibration ratios

        The statistical smoke compares two live timing medians against a fixed fourfold ratio. Very fast operations can calibrate into dissimilar observed slices under scheduler and timer noise even though both slices are valid, causing intermittent Program_Error before the benchmark API is exercised further.

        Solution: Validate timed-slice validity instead of proximity

        Require both retained median batch durations to be positive. The smoke still verifies that equal-time comparison produced timed samples and separately verifies the configured batching policy, without treating host timing noise as a correctness failure.

      6. f628b406
        Problem: Interference smoke requires observable host load

        The retake and pause checks require a helper process to cross a tick-based host CPU counter window. Runner scheduling can leave no actionable contaminated window, so the test faults even though the harness reports a coherent observation.

        Solution: Validate responses only when the host observes them

        Use tick-sized interference samples and windows, retain bounded response and sample-count checks, and require pause counters, elapsed time, and retaken samples to agree. A run with no actionable external window is now a valid integration outcome.

      7. 713783bfAdd extensible benchmark metrics and manual timing
      8. cb1c0c6bFix custom metric comparison reporting
      9. 1be316cbHarden manual timing adapters
      10. 340086a7Preserve missing custom probe failures
      11. cc7a3938
        Problem: Custom metrics bypass configured statistics

        Custom metric summaries and comparisons retain fixed bootstrap sizes and 95 percent interval tails after configurable statistical policy is introduced. Their additional intervals also remain outside the aggregate bootstrap-work ceiling.

        Solution: Apply the result's statistical policy to custom metrics

        Size custom bootstrap distributions from the configured resample count, derive their interval tails from the configured confidence level, and include every registered custom metric in bootstrap-work validation.

      12. e9100447Add saved baseline regression gates
      13. 4c4382afFix baseline gate compatibility and reporting
      14. 8aba46e3Prove baseline regression arithmetic bounds
      15. fedeeb77
        Problem: Baseline gates discard statistical policy

        The regression gate fixes every independent comparison at 95 percent confidence and 2,000 resamples even when callers use another benchmark policy. This also leaves the gate's bootstrap work outside the shared safety ceiling.

        Solution: Make gate statistics explicit and bounded

        Add source-compatible defaulted confidence and resample parameters to gate evaluation, propagate them through comparison and result metadata, validate aggregate bootstrap work, and cover non-default policy retention.

      16. 0b9f10be
        Problem: Baseline equivalence smoke depends on live timing noise

        The saved and current inputs reuse one live measurement, but the independent bootstrap resamples them separately. Scheduler outliers can widen the interval beyond the fixed threshold, causing valid inconclusive results to fail the benchmark test intermittently on CI and locally.

        Solution: Exercise gate policy with deterministic samples

        Add a test-only child helper that constructs a private measurement from a fixed mildly dispersed vector. Use that measurement for equivalence, boundary, inconclusive, and reporter coverage while retaining live measurements for collection and coarse improvement/regression smoke checks.

      17. de70616e
        Problem: Benchmark floating proofs exhaust level-one budgets

        The Ratio and Time_Change postconditions leave nonlinear floating-point bounds in combined prover searches. GNATprove 16.1.0 can reach its one-second level-one prover limit on Ubuntu CI even though repeated proofs may pass locally.

        Solution: Split the floating bounds into stable proof obligations

        State Ratio bounds directly in its postcondition and retain the exact Time_Change arithmetic while asserting each difficult bound in its matching branch. The final postcondition becomes a cheap control-flow merge without raising the global proof level or changing returned values.

      18. 8b189587
        Problem: Benchmark proofs still exceed the CI prover limit

        Ubuntu GNATprove 16.1.0 still reaches the default one-second limit on the remaining Ratio monotonicity proof and the faster Time_Change bound. Further structural splits relocate the same floating-point search without reducing it.

        Solution: Give only the benchmark proof a two-second timeout

        Keep level 1 and every other proof invocation unchanged while extending the already-isolated baseline math proof budget. Record the focused budget and its rationale in the benchmark proof status.

      19. 7406db05
        Problem: Benchmark proof still exceeds its focused budget

        Ubuntu GNATprove 16.1.0 can still exhaust the isolated two-second timeout on the Ratio lower-bound postcondition after the structural proof split. This leaves otherwise valid stack heads intermittently red.

        Solution: Widen only the benchmark proof timeout

        Increase the Baseline_Math timeout to five seconds while retaining level 1 and every other proof budget. Update the proof-status record to match the executable invocation.

      20. 739287caAdd benchmark parameter sweeps and scaling analysis
      21. ce31f2e2Fix sweep availability and scaling metadata
      22. 449eff4bFix sweep availability and display reporting
      23. dbf06156Fix sweep failure and scaling states
      24. 03d277e6Fix exact sweep boundaries and reporting
      25. ac1a8781Test final sweep budget stop semantics
      26. cee1d4abAdd explicit flyology_bench suite runner
      27. 5334042aFix benchmark suite reporting and execution
      28. e1433649
        Problem: Suite context changes reporter profiles

        Adding a defaulted context formal lets ordinary calls compile but breaks source uses that depend on the exact legacy reporter profile, including access attributes, renamings, and generic actuals. Ada also forbids overloading generic units.

        Solution: Preserve legacy profiles beside contextual reporters

        Restore exact pre-suite reporter signatures as forwarding entry points, expose contextual overloads for ordinary procedures and distinctly named contextual multi-way generics, update suite bindings, and compile-check access and renaming compatibility.

      29. b5f078d4
        Problem: Suite rejection status has no baseline gate

        The suite aggregate reserves a regression-rejected outcome but registered measurements cannot evaluate a saved baseline. Users must duplicate execution and reporting logic outside the runner, and the suite cannot propagate a gate failure to its final status.

        Solution: Add explicit read-only gated registrations

        Let ordinary cases opt into a saved-baseline policy, evaluate it with the suite's effective confidence, resample, and seed settings after collection, report the gate in every output style, and give rejection precedence in the aggregate without creating or updating artifacts.

      30. a062b019
        Problem: Benchmark documentation filter is overbroad

        The GNATdoc workaround accepts any generic-formal warning from several benchmark units, so a newly undocumented public formal can pass documentation verification unnoticed.

        Solution: Match only known GNATdoc false positives

        Split the benchmark-unit filters and enumerate the exact root, reporter, sweep, and suite generic formal names that GNATdoc 26 misclassifies while continuing to reject every other warning.

      31. 962e5a48
        Problem: Benchmark smoke failures omit their Ada call chain

        Hosted-runner memory faults currently end with only a runtime Storage_Error location. The local action log cannot identify which benchmark or reporter frame raised it, so platform-only failures are not actionable from CI evidence.

        Solution: Capture symbolic test exception tracebacks

        Build test mains with debug information and GNAT symbolic exception traceback support. On smoke failure, emit the complete exception occurrence to standard error before preserving the original unhandled failure.

      32. a637cc13
        Problem: Suite smoke closes an active runner output view

        The reporting-failure scenario closes the caller's Ada.Text_IO file from inside a benchmark callback while Execute still holds and uses that file. GNAT platforms may retain a dangling internal file view, so the subsequent CSV header write can raise erroneous-memory-access instead of the Status_Error the test expects.

        Solution: Keep runner streams valid for the execution lifetime

        Remove the invalid cross-callback close scenario and document that Output and Progress must remain open and must not be reset or closed until Execute returns. Existing callback-failure tests continue to cover runner failure accounting without invoking dangling Text_IO behavior.

      33. 6f2cf34cAdd isolated benchmark worker processes
      34. 8a195f6dHarden isolated benchmark worker containment
      35. 2fb07b32Harden benchmark worker ownership validation
      36. c537aff4Harden benchmark worker result validation
      37. afb23533Protect benchmark worker environment metadata
      38. a29271b3Harden benchmark worker metadata validation
      39. 3d0ce30a
        Problem: Worker mode duplicates suite case dispatch

        Fresh-process executables must currently reconstruct case selection beside the suite registry, so the parent identity and worker callback can drift. Readiness and result return are also repeated in each worker main.

        Solution: Execute worker requests through the suite registry

        Validate the requested identity and result kind against an exact registration, rebuild worker-local configuration, announce readiness, invoke Execute_One, and return the matching protocol result. Update the maintained example to use this shared dispatch path.

      40. c9c465f1
        Merge pull request #67 from flyology-ada/codex/bench-06-process-workers

        Add fresh-process benchmark workers

      41. 6b7273a1
        Problem: Ada formatting policy is inconsistent across the repository

        Flyology and its standalone subcrates lack one enforced line-length and encoding policy. GNAT-preprocessed units also require a documented path that preserves every conditional branch.

        Solution: Standardize Ada formatting at 110 columns

        Configure each owning project for 110-column UTF-8 GNATformat output and matching compiler checks, align runtime compilation, document the preprocessing workflow, and reformat all tracked handwritten Ada sources.

      42. ccf08b27
        Problem: Ada preprocessing blocks uniform formatting of test seams

        GNATformat skips Ada units containing preprocessing directives, while the former test-hook switches made production code generation depend on a preprocessing pass. The repository also lacked an isolated regression proving that every hook selection is correct and that disabled calls disappear at all supported optimization levels.

        Solution: Select hook packages through GPR source directories

        Replace Ada directives with documented enabled and disabled private package variants, guard hook references with literal constants, and expose imported sentinels for missed guards. Add a dedicated cross-platform CI job that checks all 256 selections, optimization modes, and production archives without adding the exhaustive pass to the ordinary test suite.

      43. edf9d8c0
        Problem: Formatted sources fail Linux and Pages validation

        GNAT's runtime style checker rejects a formatter-shifted comment in the Linux file engine, preventing runtime assembly. GNATformat also separates three leading GNATdoc @exclude tags from their declarations, causing the Pages build to report those internal adapter instances as undocumented public API.

        Solution: Restore validation-sensitive comment placement

        Place the runtime comment in the GNAT style column, keep each @exclude tag adjacent to its declaration, and document the GNATformat exception in the agent guide.

      44. 2987d103
        Problem: multiplexed protocol operations cannot compose outbound wakeups

        An owner-stack connection protocol can arm hidden transport and lifecycle readiness through a Capability, but it cannot include the opaque Outbound_Wakeup used by concurrent stream publishers. Multiplexed clients therefore lack one bounded wait set and would need a helper pump or exposed descriptor.

        Solution: compose outbound publication with transport arming

        Add the narrow Arm_Transport overload that arms the required hidden transport direction, outbound wake source, and lifecycle sources on one outer operation. Consume already-pending notifications before rescheduling to prevent stale-signal spin, preserve independent deadlines, and cover pending, later-signal, reuse, TLS, deadline, native, and lightweight paths.

      45. 3815cc9d
        Problem: scoped socket children cannot compose lifecycle wake sources

        Established stream and datagram operations can block on transport readiness, but most scoped stream calls and Receive_Datagram cannot include caller-owned cancellation or protocol-output descriptors. DNS, HTTP/2, and HTTP/3 parents therefore cannot wake hidden socket work without a helper.

        Solution: add bounded interrupt sets to scoped socket operations

        Add source-compatible Interrupts parameters to scoped stream array operations and datagram receive roots, copy the bounded descriptor set into caller-owned operation storage, and arm it with transport readiness. Retain typed interruption and device failures and cover already-pending and later-signalled datagram interrupts in native and lightweight lanes.

      46. ebf80d6b
        Problem: DNS resolution cannot compose with scoped client operations

        Flyology.IO.DNS exposes only synchronous Resolve calls, so an HTTP parent cannot preserve one owner-stack deadline and cancellation scope while resolving an origin. Wrapping the synchronous resolver would block a lightweight event-loop pthread and cannot participate in Continue_After or completion gates.

        Solution: implement a bounded scoped DNS resolver state machine

        Add reusable resolver configuration snapshots, limited Resolve operations with root and established starts, and typed Finish parity. Drive numeric, localhost, cache, search, family, retry, UDP, TCP fallback, token, deadline, and cancellation paths through hidden scoped socket children, with transactional capacity rollback and complete drain-before-publication tests in both lanes.

      47. c6b1bffc
        Merge pull request #75 from flyology-ada/codex/scoped-dns-resolver

        Add composable scoped DNS resolution

    3. c6b1bffc updated to 417e48adindex f41acb68

      2 source commits

      1. 56a47436
        Problem: Scoped transports cannot compose all readiness sources

        HTTP multiplexing needs one operation to wait on hidden transport, outbound,
        lifecycle, token, and caller-source descriptors. The four-source bound overflows
        H2, and datagram receives cannot express a direction-sensitive caller source
        for H3.

        Solution: Raise readiness capacity and add caller-source arming overloads

        Raise the operation, public I/O, and runtime limits to six interests per
        operation. Add connection and datagram overloads that include one validated,
        caller-borrowed read-or-write descriptor in the existing bounded wait, retain
        the outbound consume-before-reschedule rule, and cover native and lightweight
        readiness, race, deadline, cancellation, and reuse behavior.

      2. 417e48ad
        Compose six scoped transport readiness sources (#76)

        Preserve the reviewed Problem/Solution prerequisite commit and merge it after the complete Linux/macOS, SPARK, TLA+, and Pages matrix passed.

    Compare source revisions
    Development update

    flyology_debug 0.1.1-dev

    3 updates: ef6841e7 through 417e48ad

    Bounded in-memory tracing and gauges for Ada

    Manifest fields
    origin
    Show all 3 updates
    1. ef6841e7 updated to 4ec71932index 73e6c1b5

      7 source commits

      1. c9ccf71b
        Problem: Running servers cannot change generations without losing continuity

        Flyology lacks a generation protocol, listener-capability handoff, and coordinated canary lifecycle for replacing a running server with a changed executable. Operators cannot prepare, admit, promote, cancel, drain, fence, or reverse generations through one reviewed ownership model.

        Solution: Add supervised process-generation upgrades and executable guide

        Implement the Ada-owned coordinator and agent protocol, narrow descriptor and bootstrap handoff mechanisms, lifecycle policy, ABI and behavioral checks, and a mechanically extracted two-artifact website guide that exercises promotion and cancellation.

      2. 1fb1025e
        Problem: The upgrade guide does not identify the demo service

        Readers can follow coordinator calls without knowing what behavior changes between the two artifacts or what the verification request proves.

        Solution: Explain the example server and its observable cutover

        Describe the one-byte request/reply behavior, the distinct generation replies, and how promotion and cancellation assertions relate to new connections.

      3. 5ec82af6
        Merge pull request #61 from flyology-ada/codex/process-upgrades

        Add supervised process-generation upgrades

      4. 270984a3
        Problem: Benchmark CI failures hide their local test log

        The standalone flyology_bench Alire action captures command output in alire/alr_test_local.log. Hosted failures currently retain only Alire’s generic wrapper, so maintainers cannot identify which redirected smoke executable or assertion failed.

        Solution: Surface benchmark test diagnostics on failure

        Print the tail of the captured Alire log while preserving the original status, and label the two redirected smoke executables so the retained log names the active command. Successful test output remains unchanged apart from the command labels.

      5. 0081ba78
        Problem: Benchmark smoke counter overflows on fast hosts

        The flyology_bench smoke fixture accumulates every calibrated operation in a Natural. Fast x86-64 runners can execute more than Natural Last operations across the suite, raising Constraint_Error before the runtime-specific tests begin.

        Solution: Use a modular 64-bit operation counter

        Store the volatile sink and scheduler-probe value directly as Interfaces.Unsigned_64. The counter now retains the intended observable work signal without a checked 32-bit accumulation limit.

      6. 04ff6dcd
        Add direct managed client connections (#70)

        * Problem: Managed clients require raw socket adoption boilerplate

        Composable protocol clients need a managed Flyology connection before they can use the public connection driver, but callers must create and connect a raw socket and then transfer it through Take. This obscures the admission, deadline, cancellation, and cleanup boundary.

        Solution: Add a direct managed connection path

        Add Connections.Connect to reserve admission, create and connect the endpoint-family socket under one deadline, and atomically adopt it with existing guards. Cover both lanes, failure cleanup, TLS and driver composition, and document raw and managed client choices.

        * Problem: The managed connection test iterates a platform type

        Execution_Model is discrete on Darwin but an access type on Linux, so iterating its subtype prevents the new smoke test from compiling on a supported platform. The Darwin loop also repeats the configured project default rather than naming the two lanes under test.

        Solution: Run the two execution lanes explicitly

        Move the scenarios into Run_All and invoke it once for Lightweight_Task and once for Native_Task. This preserves the intended parity coverage without platform-dependent subtype iteration or a redundant default-lane pass.

      7. 4ec71932
        Add scoped managed connection construction (#72)

        * Problem: Managed connection setup cannot join completion sets

        * Problem: Managed connect lacks a selective-wait regression

        The scoped construction tests use Wait_All, so they do not directly prove that a managed connect remains visible as one parent result while its hidden child is excluded from a heterogeneous success gate.

        Solution: exercise managed connect with a timer success gate

        Run the gate in both execution models, transfer the winning connection through typed Finish, cancel the timer sibling, and assert peer-close and admission cleanup.

    2. 4ec71932 updated to c6b1bffcindex 980bb9e5

      47 source commits

      1. 12eb5e12Problem: Benchmark confidence policy is fixed
      2. a9567c3bProblem: Bootstrap settings permit pathological analysis
      3. 2a4f4862
        Problem: Benchmark documentation links target a stale API anchor

        The statistical-policy changes alter the generated GNATdoc identity for Compare_Independent. The benchmarking guide and comparison journal retain the previous fragment, so the Pages link checker rejects the site built for PR #62.

        Solution: Point both links at the regenerated entity anchor

        Update the two deep links to the fragment emitted for Compare_Independent by the current flyology_bench API documentation.

      4. 98f7201a
        Problem: Statistical smoke retains a stale counter type

        Current main widens the benchmark smoke counter to Unsigned_64 so fast hosts cannot overflow it. The statistical-policy layer snapshots that counter as Natural, making the rebased stack fail compilation before any benchmark runs.

        Solution: Match the snapshot to the widened counter

        Store the pre-execution snapshot as Interfaces.Unsigned_64 so assignment and comparison remain type-correct across the counter full range.

      5. 1c7a45e4
        Problem: Equal-time smoke faults on noisy calibration ratios

        The statistical smoke compares two live timing medians against a fixed fourfold ratio. Very fast operations can calibrate into dissimilar observed slices under scheduler and timer noise even though both slices are valid, causing intermittent Program_Error before the benchmark API is exercised further.

        Solution: Validate timed-slice validity instead of proximity

        Require both retained median batch durations to be positive. The smoke still verifies that equal-time comparison produced timed samples and separately verifies the configured batching policy, without treating host timing noise as a correctness failure.

      6. f628b406
        Problem: Interference smoke requires observable host load

        The retake and pause checks require a helper process to cross a tick-based host CPU counter window. Runner scheduling can leave no actionable contaminated window, so the test faults even though the harness reports a coherent observation.

        Solution: Validate responses only when the host observes them

        Use tick-sized interference samples and windows, retain bounded response and sample-count checks, and require pause counters, elapsed time, and retaken samples to agree. A run with no actionable external window is now a valid integration outcome.

      7. 713783bfAdd extensible benchmark metrics and manual timing
      8. cb1c0c6bFix custom metric comparison reporting
      9. 1be316cbHarden manual timing adapters
      10. 340086a7Preserve missing custom probe failures
      11. cc7a3938
        Problem: Custom metrics bypass configured statistics

        Custom metric summaries and comparisons retain fixed bootstrap sizes and 95 percent interval tails after configurable statistical policy is introduced. Their additional intervals also remain outside the aggregate bootstrap-work ceiling.

        Solution: Apply the result's statistical policy to custom metrics

        Size custom bootstrap distributions from the configured resample count, derive their interval tails from the configured confidence level, and include every registered custom metric in bootstrap-work validation.

      12. e9100447Add saved baseline regression gates
      13. 4c4382afFix baseline gate compatibility and reporting
      14. 8aba46e3Prove baseline regression arithmetic bounds
      15. fedeeb77
        Problem: Baseline gates discard statistical policy

        The regression gate fixes every independent comparison at 95 percent confidence and 2,000 resamples even when callers use another benchmark policy. This also leaves the gate's bootstrap work outside the shared safety ceiling.

        Solution: Make gate statistics explicit and bounded

        Add source-compatible defaulted confidence and resample parameters to gate evaluation, propagate them through comparison and result metadata, validate aggregate bootstrap work, and cover non-default policy retention.

      16. 0b9f10be
        Problem: Baseline equivalence smoke depends on live timing noise

        The saved and current inputs reuse one live measurement, but the independent bootstrap resamples them separately. Scheduler outliers can widen the interval beyond the fixed threshold, causing valid inconclusive results to fail the benchmark test intermittently on CI and locally.

        Solution: Exercise gate policy with deterministic samples

        Add a test-only child helper that constructs a private measurement from a fixed mildly dispersed vector. Use that measurement for equivalence, boundary, inconclusive, and reporter coverage while retaining live measurements for collection and coarse improvement/regression smoke checks.

      17. de70616e
        Problem: Benchmark floating proofs exhaust level-one budgets

        The Ratio and Time_Change postconditions leave nonlinear floating-point bounds in combined prover searches. GNATprove 16.1.0 can reach its one-second level-one prover limit on Ubuntu CI even though repeated proofs may pass locally.

        Solution: Split the floating bounds into stable proof obligations

        State Ratio bounds directly in its postcondition and retain the exact Time_Change arithmetic while asserting each difficult bound in its matching branch. The final postcondition becomes a cheap control-flow merge without raising the global proof level or changing returned values.

      18. 8b189587
        Problem: Benchmark proofs still exceed the CI prover limit

        Ubuntu GNATprove 16.1.0 still reaches the default one-second limit on the remaining Ratio monotonicity proof and the faster Time_Change bound. Further structural splits relocate the same floating-point search without reducing it.

        Solution: Give only the benchmark proof a two-second timeout

        Keep level 1 and every other proof invocation unchanged while extending the already-isolated baseline math proof budget. Record the focused budget and its rationale in the benchmark proof status.

      19. 7406db05
        Problem: Benchmark proof still exceeds its focused budget

        Ubuntu GNATprove 16.1.0 can still exhaust the isolated two-second timeout on the Ratio lower-bound postcondition after the structural proof split. This leaves otherwise valid stack heads intermittently red.

        Solution: Widen only the benchmark proof timeout

        Increase the Baseline_Math timeout to five seconds while retaining level 1 and every other proof budget. Update the proof-status record to match the executable invocation.

      20. 739287caAdd benchmark parameter sweeps and scaling analysis
      21. ce31f2e2Fix sweep availability and scaling metadata
      22. 449eff4bFix sweep availability and display reporting
      23. dbf06156Fix sweep failure and scaling states
      24. 03d277e6Fix exact sweep boundaries and reporting
      25. ac1a8781Test final sweep budget stop semantics
      26. cee1d4abAdd explicit flyology_bench suite runner
      27. 5334042aFix benchmark suite reporting and execution
      28. e1433649
        Problem: Suite context changes reporter profiles

        Adding a defaulted context formal lets ordinary calls compile but breaks source uses that depend on the exact legacy reporter profile, including access attributes, renamings, and generic actuals. Ada also forbids overloading generic units.

        Solution: Preserve legacy profiles beside contextual reporters

        Restore exact pre-suite reporter signatures as forwarding entry points, expose contextual overloads for ordinary procedures and distinctly named contextual multi-way generics, update suite bindings, and compile-check access and renaming compatibility.

      29. b5f078d4
        Problem: Suite rejection status has no baseline gate

        The suite aggregate reserves a regression-rejected outcome but registered measurements cannot evaluate a saved baseline. Users must duplicate execution and reporting logic outside the runner, and the suite cannot propagate a gate failure to its final status.

        Solution: Add explicit read-only gated registrations

        Let ordinary cases opt into a saved-baseline policy, evaluate it with the suite's effective confidence, resample, and seed settings after collection, report the gate in every output style, and give rejection precedence in the aggregate without creating or updating artifacts.

      30. a062b019
        Problem: Benchmark documentation filter is overbroad

        The GNATdoc workaround accepts any generic-formal warning from several benchmark units, so a newly undocumented public formal can pass documentation verification unnoticed.

        Solution: Match only known GNATdoc false positives

        Split the benchmark-unit filters and enumerate the exact root, reporter, sweep, and suite generic formal names that GNATdoc 26 misclassifies while continuing to reject every other warning.

      31. 962e5a48
        Problem: Benchmark smoke failures omit their Ada call chain

        Hosted-runner memory faults currently end with only a runtime Storage_Error location. The local action log cannot identify which benchmark or reporter frame raised it, so platform-only failures are not actionable from CI evidence.

        Solution: Capture symbolic test exception tracebacks

        Build test mains with debug information and GNAT symbolic exception traceback support. On smoke failure, emit the complete exception occurrence to standard error before preserving the original unhandled failure.

      32. a637cc13
        Problem: Suite smoke closes an active runner output view

        The reporting-failure scenario closes the caller's Ada.Text_IO file from inside a benchmark callback while Execute still holds and uses that file. GNAT platforms may retain a dangling internal file view, so the subsequent CSV header write can raise erroneous-memory-access instead of the Status_Error the test expects.

        Solution: Keep runner streams valid for the execution lifetime

        Remove the invalid cross-callback close scenario and document that Output and Progress must remain open and must not be reset or closed until Execute returns. Existing callback-failure tests continue to cover runner failure accounting without invoking dangling Text_IO behavior.

      33. 6f2cf34cAdd isolated benchmark worker processes
      34. 8a195f6dHarden isolated benchmark worker containment
      35. 2fb07b32Harden benchmark worker ownership validation
      36. c537aff4Harden benchmark worker result validation
      37. afb23533Protect benchmark worker environment metadata
      38. a29271b3Harden benchmark worker metadata validation
      39. 3d0ce30a
        Problem: Worker mode duplicates suite case dispatch

        Fresh-process executables must currently reconstruct case selection beside the suite registry, so the parent identity and worker callback can drift. Readiness and result return are also repeated in each worker main.

        Solution: Execute worker requests through the suite registry

        Validate the requested identity and result kind against an exact registration, rebuild worker-local configuration, announce readiness, invoke Execute_One, and return the matching protocol result. Update the maintained example to use this shared dispatch path.

      40. c9c465f1
        Merge pull request #67 from flyology-ada/codex/bench-06-process-workers

        Add fresh-process benchmark workers

      41. 6b7273a1
        Problem: Ada formatting policy is inconsistent across the repository

        Flyology and its standalone subcrates lack one enforced line-length and encoding policy. GNAT-preprocessed units also require a documented path that preserves every conditional branch.

        Solution: Standardize Ada formatting at 110 columns

        Configure each owning project for 110-column UTF-8 GNATformat output and matching compiler checks, align runtime compilation, document the preprocessing workflow, and reformat all tracked handwritten Ada sources.

      42. ccf08b27
        Problem: Ada preprocessing blocks uniform formatting of test seams

        GNATformat skips Ada units containing preprocessing directives, while the former test-hook switches made production code generation depend on a preprocessing pass. The repository also lacked an isolated regression proving that every hook selection is correct and that disabled calls disappear at all supported optimization levels.

        Solution: Select hook packages through GPR source directories

        Replace Ada directives with documented enabled and disabled private package variants, guard hook references with literal constants, and expose imported sentinels for missed guards. Add a dedicated cross-platform CI job that checks all 256 selections, optimization modes, and production archives without adding the exhaustive pass to the ordinary test suite.

      43. edf9d8c0
        Problem: Formatted sources fail Linux and Pages validation

        GNAT's runtime style checker rejects a formatter-shifted comment in the Linux file engine, preventing runtime assembly. GNATformat also separates three leading GNATdoc @exclude tags from their declarations, causing the Pages build to report those internal adapter instances as undocumented public API.

        Solution: Restore validation-sensitive comment placement

        Place the runtime comment in the GNAT style column, keep each @exclude tag adjacent to its declaration, and document the GNATformat exception in the agent guide.

      44. 2987d103
        Problem: multiplexed protocol operations cannot compose outbound wakeups

        An owner-stack connection protocol can arm hidden transport and lifecycle readiness through a Capability, but it cannot include the opaque Outbound_Wakeup used by concurrent stream publishers. Multiplexed clients therefore lack one bounded wait set and would need a helper pump or exposed descriptor.

        Solution: compose outbound publication with transport arming

        Add the narrow Arm_Transport overload that arms the required hidden transport direction, outbound wake source, and lifecycle sources on one outer operation. Consume already-pending notifications before rescheduling to prevent stale-signal spin, preserve independent deadlines, and cover pending, later-signal, reuse, TLS, deadline, native, and lightweight paths.

      45. 3815cc9d
        Problem: scoped socket children cannot compose lifecycle wake sources

        Established stream and datagram operations can block on transport readiness, but most scoped stream calls and Receive_Datagram cannot include caller-owned cancellation or protocol-output descriptors. DNS, HTTP/2, and HTTP/3 parents therefore cannot wake hidden socket work without a helper.

        Solution: add bounded interrupt sets to scoped socket operations

        Add source-compatible Interrupts parameters to scoped stream array operations and datagram receive roots, copy the bounded descriptor set into caller-owned operation storage, and arm it with transport readiness. Retain typed interruption and device failures and cover already-pending and later-signalled datagram interrupts in native and lightweight lanes.

      46. ebf80d6b
        Problem: DNS resolution cannot compose with scoped client operations

        Flyology.IO.DNS exposes only synchronous Resolve calls, so an HTTP parent cannot preserve one owner-stack deadline and cancellation scope while resolving an origin. Wrapping the synchronous resolver would block a lightweight event-loop pthread and cannot participate in Continue_After or completion gates.

        Solution: implement a bounded scoped DNS resolver state machine

        Add reusable resolver configuration snapshots, limited Resolve operations with root and established starts, and typed Finish parity. Drive numeric, localhost, cache, search, family, retry, UDP, TCP fallback, token, deadline, and cancellation paths through hidden scoped socket children, with transactional capacity rollback and complete drain-before-publication tests in both lanes.

      47. c6b1bffc
        Merge pull request #75 from flyology-ada/codex/scoped-dns-resolver

        Add composable scoped DNS resolution

    3. c6b1bffc updated to 417e48adindex f41acb68

      2 source commits

      1. 56a47436
        Problem: Scoped transports cannot compose all readiness sources

        HTTP multiplexing needs one operation to wait on hidden transport, outbound,
        lifecycle, token, and caller-source descriptors. The four-source bound overflows
        H2, and datagram receives cannot express a direction-sensitive caller source
        for H3.

        Solution: Raise readiness capacity and add caller-source arming overloads

        Raise the operation, public I/O, and runtime limits to six interests per
        operation. Add connection and datagram overloads that include one validated,
        caller-borrowed read-or-write descriptor in the existing bounded wait, retain
        the outbound consume-before-reschedule rule, and cover native and lightweight
        readiness, race, deadline, cancellation, and reuse behavior.

      2. 417e48ad
        Compose six scoped transport readiness sources (#76)

        Preserve the reviewed Problem/Solution prerequisite commit and merge it after the complete Linux/macOS, SPARK, TLA+, and Pages matrix passed.

    Compare source revisions
    Development update

    flyology_numa 0.1.0-dev

    3 updates: ef6841e7 through 417e48ad

    Memory-node topology reporting for Ada

    Manifest fields
    origin
    Show all 3 updates
    1. ef6841e7 updated to 4ec71932index 73e6c1b5

      7 source commits

      1. c9ccf71b
        Problem: Running servers cannot change generations without losing continuity

        Flyology lacks a generation protocol, listener-capability handoff, and coordinated canary lifecycle for replacing a running server with a changed executable. Operators cannot prepare, admit, promote, cancel, drain, fence, or reverse generations through one reviewed ownership model.

        Solution: Add supervised process-generation upgrades and executable guide

        Implement the Ada-owned coordinator and agent protocol, narrow descriptor and bootstrap handoff mechanisms, lifecycle policy, ABI and behavioral checks, and a mechanically extracted two-artifact website guide that exercises promotion and cancellation.

      2. 1fb1025e
        Problem: The upgrade guide does not identify the demo service

        Readers can follow coordinator calls without knowing what behavior changes between the two artifacts or what the verification request proves.

        Solution: Explain the example server and its observable cutover

        Describe the one-byte request/reply behavior, the distinct generation replies, and how promotion and cancellation assertions relate to new connections.

      3. 5ec82af6
        Merge pull request #61 from flyology-ada/codex/process-upgrades

        Add supervised process-generation upgrades

      4. 270984a3
        Problem: Benchmark CI failures hide their local test log

        The standalone flyology_bench Alire action captures command output in alire/alr_test_local.log. Hosted failures currently retain only Alire’s generic wrapper, so maintainers cannot identify which redirected smoke executable or assertion failed.

        Solution: Surface benchmark test diagnostics on failure

        Print the tail of the captured Alire log while preserving the original status, and label the two redirected smoke executables so the retained log names the active command. Successful test output remains unchanged apart from the command labels.

      5. 0081ba78
        Problem: Benchmark smoke counter overflows on fast hosts

        The flyology_bench smoke fixture accumulates every calibrated operation in a Natural. Fast x86-64 runners can execute more than Natural Last operations across the suite, raising Constraint_Error before the runtime-specific tests begin.

        Solution: Use a modular 64-bit operation counter

        Store the volatile sink and scheduler-probe value directly as Interfaces.Unsigned_64. The counter now retains the intended observable work signal without a checked 32-bit accumulation limit.

      6. 04ff6dcd
        Add direct managed client connections (#70)

        * Problem: Managed clients require raw socket adoption boilerplate

        Composable protocol clients need a managed Flyology connection before they can use the public connection driver, but callers must create and connect a raw socket and then transfer it through Take. This obscures the admission, deadline, cancellation, and cleanup boundary.

        Solution: Add a direct managed connection path

        Add Connections.Connect to reserve admission, create and connect the endpoint-family socket under one deadline, and atomically adopt it with existing guards. Cover both lanes, failure cleanup, TLS and driver composition, and document raw and managed client choices.

        * Problem: The managed connection test iterates a platform type

        Execution_Model is discrete on Darwin but an access type on Linux, so iterating its subtype prevents the new smoke test from compiling on a supported platform. The Darwin loop also repeats the configured project default rather than naming the two lanes under test.

        Solution: Run the two execution lanes explicitly

        Move the scenarios into Run_All and invoke it once for Lightweight_Task and once for Native_Task. This preserves the intended parity coverage without platform-dependent subtype iteration or a redundant default-lane pass.

      7. 4ec71932
        Add scoped managed connection construction (#72)

        * Problem: Managed connection setup cannot join completion sets

        * Problem: Managed connect lacks a selective-wait regression

        The scoped construction tests use Wait_All, so they do not directly prove that a managed connect remains visible as one parent result while its hidden child is excluded from a heterogeneous success gate.

        Solution: exercise managed connect with a timer success gate

        Run the gate in both execution models, transfer the winning connection through typed Finish, cancel the timer sibling, and assert peer-close and admission cleanup.

    2. 4ec71932 updated to c6b1bffcindex 980bb9e5

      47 source commits

      1. 12eb5e12Problem: Benchmark confidence policy is fixed
      2. a9567c3bProblem: Bootstrap settings permit pathological analysis
      3. 2a4f4862
        Problem: Benchmark documentation links target a stale API anchor

        The statistical-policy changes alter the generated GNATdoc identity for Compare_Independent. The benchmarking guide and comparison journal retain the previous fragment, so the Pages link checker rejects the site built for PR #62.

        Solution: Point both links at the regenerated entity anchor

        Update the two deep links to the fragment emitted for Compare_Independent by the current flyology_bench API documentation.

      4. 98f7201a
        Problem: Statistical smoke retains a stale counter type

        Current main widens the benchmark smoke counter to Unsigned_64 so fast hosts cannot overflow it. The statistical-policy layer snapshots that counter as Natural, making the rebased stack fail compilation before any benchmark runs.

        Solution: Match the snapshot to the widened counter

        Store the pre-execution snapshot as Interfaces.Unsigned_64 so assignment and comparison remain type-correct across the counter full range.

      5. 1c7a45e4
        Problem: Equal-time smoke faults on noisy calibration ratios

        The statistical smoke compares two live timing medians against a fixed fourfold ratio. Very fast operations can calibrate into dissimilar observed slices under scheduler and timer noise even though both slices are valid, causing intermittent Program_Error before the benchmark API is exercised further.

        Solution: Validate timed-slice validity instead of proximity

        Require both retained median batch durations to be positive. The smoke still verifies that equal-time comparison produced timed samples and separately verifies the configured batching policy, without treating host timing noise as a correctness failure.

      6. f628b406
        Problem: Interference smoke requires observable host load

        The retake and pause checks require a helper process to cross a tick-based host CPU counter window. Runner scheduling can leave no actionable contaminated window, so the test faults even though the harness reports a coherent observation.

        Solution: Validate responses only when the host observes them

        Use tick-sized interference samples and windows, retain bounded response and sample-count checks, and require pause counters, elapsed time, and retaken samples to agree. A run with no actionable external window is now a valid integration outcome.

      7. 713783bfAdd extensible benchmark metrics and manual timing
      8. cb1c0c6bFix custom metric comparison reporting
      9. 1be316cbHarden manual timing adapters
      10. 340086a7Preserve missing custom probe failures
      11. cc7a3938
        Problem: Custom metrics bypass configured statistics

        Custom metric summaries and comparisons retain fixed bootstrap sizes and 95 percent interval tails after configurable statistical policy is introduced. Their additional intervals also remain outside the aggregate bootstrap-work ceiling.

        Solution: Apply the result's statistical policy to custom metrics

        Size custom bootstrap distributions from the configured resample count, derive their interval tails from the configured confidence level, and include every registered custom metric in bootstrap-work validation.

      12. e9100447Add saved baseline regression gates
      13. 4c4382afFix baseline gate compatibility and reporting
      14. 8aba46e3Prove baseline regression arithmetic bounds
      15. fedeeb77
        Problem: Baseline gates discard statistical policy

        The regression gate fixes every independent comparison at 95 percent confidence and 2,000 resamples even when callers use another benchmark policy. This also leaves the gate's bootstrap work outside the shared safety ceiling.

        Solution: Make gate statistics explicit and bounded

        Add source-compatible defaulted confidence and resample parameters to gate evaluation, propagate them through comparison and result metadata, validate aggregate bootstrap work, and cover non-default policy retention.

      16. 0b9f10be
        Problem: Baseline equivalence smoke depends on live timing noise

        The saved and current inputs reuse one live measurement, but the independent bootstrap resamples them separately. Scheduler outliers can widen the interval beyond the fixed threshold, causing valid inconclusive results to fail the benchmark test intermittently on CI and locally.

        Solution: Exercise gate policy with deterministic samples

        Add a test-only child helper that constructs a private measurement from a fixed mildly dispersed vector. Use that measurement for equivalence, boundary, inconclusive, and reporter coverage while retaining live measurements for collection and coarse improvement/regression smoke checks.

      17. de70616e
        Problem: Benchmark floating proofs exhaust level-one budgets

        The Ratio and Time_Change postconditions leave nonlinear floating-point bounds in combined prover searches. GNATprove 16.1.0 can reach its one-second level-one prover limit on Ubuntu CI even though repeated proofs may pass locally.

        Solution: Split the floating bounds into stable proof obligations

        State Ratio bounds directly in its postcondition and retain the exact Time_Change arithmetic while asserting each difficult bound in its matching branch. The final postcondition becomes a cheap control-flow merge without raising the global proof level or changing returned values.

      18. 8b189587
        Problem: Benchmark proofs still exceed the CI prover limit

        Ubuntu GNATprove 16.1.0 still reaches the default one-second limit on the remaining Ratio monotonicity proof and the faster Time_Change bound. Further structural splits relocate the same floating-point search without reducing it.

        Solution: Give only the benchmark proof a two-second timeout

        Keep level 1 and every other proof invocation unchanged while extending the already-isolated baseline math proof budget. Record the focused budget and its rationale in the benchmark proof status.

      19. 7406db05
        Problem: Benchmark proof still exceeds its focused budget

        Ubuntu GNATprove 16.1.0 can still exhaust the isolated two-second timeout on the Ratio lower-bound postcondition after the structural proof split. This leaves otherwise valid stack heads intermittently red.

        Solution: Widen only the benchmark proof timeout

        Increase the Baseline_Math timeout to five seconds while retaining level 1 and every other proof budget. Update the proof-status record to match the executable invocation.

      20. 739287caAdd benchmark parameter sweeps and scaling analysis
      21. ce31f2e2Fix sweep availability and scaling metadata
      22. 449eff4bFix sweep availability and display reporting
      23. dbf06156Fix sweep failure and scaling states
      24. 03d277e6Fix exact sweep boundaries and reporting
      25. ac1a8781Test final sweep budget stop semantics
      26. cee1d4abAdd explicit flyology_bench suite runner
      27. 5334042aFix benchmark suite reporting and execution
      28. e1433649
        Problem: Suite context changes reporter profiles

        Adding a defaulted context formal lets ordinary calls compile but breaks source uses that depend on the exact legacy reporter profile, including access attributes, renamings, and generic actuals. Ada also forbids overloading generic units.

        Solution: Preserve legacy profiles beside contextual reporters

        Restore exact pre-suite reporter signatures as forwarding entry points, expose contextual overloads for ordinary procedures and distinctly named contextual multi-way generics, update suite bindings, and compile-check access and renaming compatibility.

      29. b5f078d4
        Problem: Suite rejection status has no baseline gate

        The suite aggregate reserves a regression-rejected outcome but registered measurements cannot evaluate a saved baseline. Users must duplicate execution and reporting logic outside the runner, and the suite cannot propagate a gate failure to its final status.

        Solution: Add explicit read-only gated registrations

        Let ordinary cases opt into a saved-baseline policy, evaluate it with the suite's effective confidence, resample, and seed settings after collection, report the gate in every output style, and give rejection precedence in the aggregate without creating or updating artifacts.

      30. a062b019
        Problem: Benchmark documentation filter is overbroad

        The GNATdoc workaround accepts any generic-formal warning from several benchmark units, so a newly undocumented public formal can pass documentation verification unnoticed.

        Solution: Match only known GNATdoc false positives

        Split the benchmark-unit filters and enumerate the exact root, reporter, sweep, and suite generic formal names that GNATdoc 26 misclassifies while continuing to reject every other warning.

      31. 962e5a48
        Problem: Benchmark smoke failures omit their Ada call chain

        Hosted-runner memory faults currently end with only a runtime Storage_Error location. The local action log cannot identify which benchmark or reporter frame raised it, so platform-only failures are not actionable from CI evidence.

        Solution: Capture symbolic test exception tracebacks

        Build test mains with debug information and GNAT symbolic exception traceback support. On smoke failure, emit the complete exception occurrence to standard error before preserving the original unhandled failure.

      32. a637cc13
        Problem: Suite smoke closes an active runner output view

        The reporting-failure scenario closes the caller's Ada.Text_IO file from inside a benchmark callback while Execute still holds and uses that file. GNAT platforms may retain a dangling internal file view, so the subsequent CSV header write can raise erroneous-memory-access instead of the Status_Error the test expects.

        Solution: Keep runner streams valid for the execution lifetime

        Remove the invalid cross-callback close scenario and document that Output and Progress must remain open and must not be reset or closed until Execute returns. Existing callback-failure tests continue to cover runner failure accounting without invoking dangling Text_IO behavior.

      33. 6f2cf34cAdd isolated benchmark worker processes
      34. 8a195f6dHarden isolated benchmark worker containment
      35. 2fb07b32Harden benchmark worker ownership validation
      36. c537aff4Harden benchmark worker result validation
      37. afb23533Protect benchmark worker environment metadata
      38. a29271b3Harden benchmark worker metadata validation
      39. 3d0ce30a
        Problem: Worker mode duplicates suite case dispatch

        Fresh-process executables must currently reconstruct case selection beside the suite registry, so the parent identity and worker callback can drift. Readiness and result return are also repeated in each worker main.

        Solution: Execute worker requests through the suite registry

        Validate the requested identity and result kind against an exact registration, rebuild worker-local configuration, announce readiness, invoke Execute_One, and return the matching protocol result. Update the maintained example to use this shared dispatch path.

      40. c9c465f1
        Merge pull request #67 from flyology-ada/codex/bench-06-process-workers

        Add fresh-process benchmark workers

      41. 6b7273a1
        Problem: Ada formatting policy is inconsistent across the repository

        Flyology and its standalone subcrates lack one enforced line-length and encoding policy. GNAT-preprocessed units also require a documented path that preserves every conditional branch.

        Solution: Standardize Ada formatting at 110 columns

        Configure each owning project for 110-column UTF-8 GNATformat output and matching compiler checks, align runtime compilation, document the preprocessing workflow, and reformat all tracked handwritten Ada sources.

      42. ccf08b27
        Problem: Ada preprocessing blocks uniform formatting of test seams

        GNATformat skips Ada units containing preprocessing directives, while the former test-hook switches made production code generation depend on a preprocessing pass. The repository also lacked an isolated regression proving that every hook selection is correct and that disabled calls disappear at all supported optimization levels.

        Solution: Select hook packages through GPR source directories

        Replace Ada directives with documented enabled and disabled private package variants, guard hook references with literal constants, and expose imported sentinels for missed guards. Add a dedicated cross-platform CI job that checks all 256 selections, optimization modes, and production archives without adding the exhaustive pass to the ordinary test suite.

      43. edf9d8c0
        Problem: Formatted sources fail Linux and Pages validation

        GNAT's runtime style checker rejects a formatter-shifted comment in the Linux file engine, preventing runtime assembly. GNATformat also separates three leading GNATdoc @exclude tags from their declarations, causing the Pages build to report those internal adapter instances as undocumented public API.

        Solution: Restore validation-sensitive comment placement

        Place the runtime comment in the GNAT style column, keep each @exclude tag adjacent to its declaration, and document the GNATformat exception in the agent guide.

      44. 2987d103
        Problem: multiplexed protocol operations cannot compose outbound wakeups

        An owner-stack connection protocol can arm hidden transport and lifecycle readiness through a Capability, but it cannot include the opaque Outbound_Wakeup used by concurrent stream publishers. Multiplexed clients therefore lack one bounded wait set and would need a helper pump or exposed descriptor.

        Solution: compose outbound publication with transport arming

        Add the narrow Arm_Transport overload that arms the required hidden transport direction, outbound wake source, and lifecycle sources on one outer operation. Consume already-pending notifications before rescheduling to prevent stale-signal spin, preserve independent deadlines, and cover pending, later-signal, reuse, TLS, deadline, native, and lightweight paths.

      45. 3815cc9d
        Problem: scoped socket children cannot compose lifecycle wake sources

        Established stream and datagram operations can block on transport readiness, but most scoped stream calls and Receive_Datagram cannot include caller-owned cancellation or protocol-output descriptors. DNS, HTTP/2, and HTTP/3 parents therefore cannot wake hidden socket work without a helper.

        Solution: add bounded interrupt sets to scoped socket operations

        Add source-compatible Interrupts parameters to scoped stream array operations and datagram receive roots, copy the bounded descriptor set into caller-owned operation storage, and arm it with transport readiness. Retain typed interruption and device failures and cover already-pending and later-signalled datagram interrupts in native and lightweight lanes.

      46. ebf80d6b
        Problem: DNS resolution cannot compose with scoped client operations

        Flyology.IO.DNS exposes only synchronous Resolve calls, so an HTTP parent cannot preserve one owner-stack deadline and cancellation scope while resolving an origin. Wrapping the synchronous resolver would block a lightweight event-loop pthread and cannot participate in Continue_After or completion gates.

        Solution: implement a bounded scoped DNS resolver state machine

        Add reusable resolver configuration snapshots, limited Resolve operations with root and established starts, and typed Finish parity. Drive numeric, localhost, cache, search, family, retry, UDP, TCP fallback, token, deadline, and cancellation paths through hidden scoped socket children, with transactional capacity rollback and complete drain-before-publication tests in both lanes.

      47. c6b1bffc
        Merge pull request #75 from flyology-ada/codex/scoped-dns-resolver

        Add composable scoped DNS resolution

    3. c6b1bffc updated to 417e48adindex f41acb68

      2 source commits

      1. 56a47436
        Problem: Scoped transports cannot compose all readiness sources

        HTTP multiplexing needs one operation to wait on hidden transport, outbound,
        lifecycle, token, and caller-source descriptors. The four-source bound overflows
        H2, and datagram receives cannot express a direction-sensitive caller source
        for H3.

        Solution: Raise readiness capacity and add caller-source arming overloads

        Raise the operation, public I/O, and runtime limits to six interests per
        operation. Add connection and datagram overloads that include one validated,
        caller-borrowed read-or-write descriptor in the existing bounded wait, retain
        the outbound consume-before-reschedule rule, and cover native and lightweight
        readiness, race, deadline, cancellation, and reuse behavior.

      2. 417e48ad
        Compose six scoped transport readiness sources (#76)

        Preserve the reviewed Problem/Solution prerequisite commit and merge it after the complete Linux/macOS, SPARK, TLA+, and Pages matrix passed.

    Compare source revisions
  25. Advance development source pins

    73e6c1b5 on GitHub
  26. Development updates

    Development update

    flyology 0.1.1-dev

    2 updates: c2db3e42 through ef6841e7

    Experimental GNAT runtime extension for native and lightweight Ada tasks

    Manifest fields
    origin
    Show all 2 updates
    1. c2db3e42 updated to 159210caindex 23c79db9

      20 source commits

      1. df4d1837Add composable scoped I/O operations
      2. 9b8f71e8Preserve scoped file timeout semantics
      3. 69a526a8Queue scoped files under submission pressure
      4. a0190f51Make operation rearming transactional
      5. ed0d6fa9Add public operation continuations
      6. 00d106aaExpand scoped file lifecycle coverage
      7. 7c4b2523Add scoped datagram operations
      8. 28b228bbAdd scoped Internet connect operations
      9. 112761c7Add scoped Internet accept operations
      10. e0ab1878Add scoped Unix socket operations
      11. 624d33c5Add owned-buffer file operations
      12. cad92a77Add scoped file watcher operations
      13. 077a9641Add composable task result operations
      14. 66896e62Add composable bounded channel operations
      15. d01d358dAdd composable buffer channel operations
      16. 7b1e6b58Complete composable connection and watcher operations
      17. 3760634bAdd composable connection TLS upgrade
      18. 1810fc60Add set-independent connection driver capability
      19. 195b2289Add composable standalone TLS operations
      20. 159210ca
        Merge pull request #60 from flyology-ada/codex/composable-operations

        Add composable scoped operations across Flyology I/O

    2. 159210ca updated to ef6841e7index fe947caf

      1 source commit

      1. ef6841e7
        Problem: Recursive Alire discovery changes shared hashes

        Flyology's dependency pre-build runs nested alr printenv commands while the outer Alire action exports deployment-specific Flyology paths. Alire hashes those inherited values and can deploy the same release twice, then reject the conflicting generated prefix.

        Solution: Isolate nested toolchain discovery

        Scrub only Flyology's root, generated configuration, and generated prefix from both recursive printenv passes. Preserve the public manifest exports and toolchain fast paths, and cover compiler and GPRbuild discovery with a deterministic stale-environment regression.

    Compare source revisions
    Development update

    flyology_allocators 0.1.0-dev

    2 updates: c2db3e42 through ef6841e7

    Caller-owned memory allocation algorithms for Ada

    Manifest fields
    origin
    Show all 2 updates
    1. c2db3e42 updated to 159210caindex 23c79db9

      20 source commits

      1. df4d1837Add composable scoped I/O operations
      2. 9b8f71e8Preserve scoped file timeout semantics
      3. 69a526a8Queue scoped files under submission pressure
      4. a0190f51Make operation rearming transactional
      5. ed0d6fa9Add public operation continuations
      6. 00d106aaExpand scoped file lifecycle coverage
      7. 7c4b2523Add scoped datagram operations
      8. 28b228bbAdd scoped Internet connect operations
      9. 112761c7Add scoped Internet accept operations
      10. e0ab1878Add scoped Unix socket operations
      11. 624d33c5Add owned-buffer file operations
      12. cad92a77Add scoped file watcher operations
      13. 077a9641Add composable task result operations
      14. 66896e62Add composable bounded channel operations
      15. d01d358dAdd composable buffer channel operations
      16. 7b1e6b58Complete composable connection and watcher operations
      17. 3760634bAdd composable connection TLS upgrade
      18. 1810fc60Add set-independent connection driver capability
      19. 195b2289Add composable standalone TLS operations
      20. 159210ca
        Merge pull request #60 from flyology-ada/codex/composable-operations

        Add composable scoped operations across Flyology I/O

    2. 159210ca updated to ef6841e7index fe947caf

      1 source commit

      1. ef6841e7
        Problem: Recursive Alire discovery changes shared hashes

        Flyology's dependency pre-build runs nested alr printenv commands while the outer Alire action exports deployment-specific Flyology paths. Alire hashes those inherited values and can deploy the same release twice, then reject the conflicting generated prefix.

        Solution: Isolate nested toolchain discovery

        Scrub only Flyology's root, generated configuration, and generated prefix from both recursive printenv passes. Preserve the public manifest exports and toolchain fast paths, and cover compiler and GPRbuild discovery with a deterministic stale-environment regression.

    Compare source revisions
    Development update

    flyology_bench 0.1.1-dev

    2 updates: c2db3e42 through ef6841e7

    Adaptive nanosecond-scale benchmarking for Ada

    Manifest fields
    origin
    Show all 2 updates
    1. c2db3e42 updated to 159210caindex 23c79db9

      20 source commits

      1. df4d1837Add composable scoped I/O operations
      2. 9b8f71e8Preserve scoped file timeout semantics
      3. 69a526a8Queue scoped files under submission pressure
      4. a0190f51Make operation rearming transactional
      5. ed0d6fa9Add public operation continuations
      6. 00d106aaExpand scoped file lifecycle coverage
      7. 7c4b2523Add scoped datagram operations
      8. 28b228bbAdd scoped Internet connect operations
      9. 112761c7Add scoped Internet accept operations
      10. e0ab1878Add scoped Unix socket operations
      11. 624d33c5Add owned-buffer file operations
      12. cad92a77Add scoped file watcher operations
      13. 077a9641Add composable task result operations
      14. 66896e62Add composable bounded channel operations
      15. d01d358dAdd composable buffer channel operations
      16. 7b1e6b58Complete composable connection and watcher operations
      17. 3760634bAdd composable connection TLS upgrade
      18. 1810fc60Add set-independent connection driver capability
      19. 195b2289Add composable standalone TLS operations
      20. 159210ca
        Merge pull request #60 from flyology-ada/codex/composable-operations

        Add composable scoped operations across Flyology I/O

    2. 159210ca updated to ef6841e7index fe947caf

      1 source commit

      1. ef6841e7
        Problem: Recursive Alire discovery changes shared hashes

        Flyology's dependency pre-build runs nested alr printenv commands while the outer Alire action exports deployment-specific Flyology paths. Alire hashes those inherited values and can deploy the same release twice, then reject the conflicting generated prefix.

        Solution: Isolate nested toolchain discovery

        Scrub only Flyology's root, generated configuration, and generated prefix from both recursive printenv passes. Preserve the public manifest exports and toolchain fast paths, and cover compiler and GPRbuild discovery with a deterministic stale-environment regression.

    Compare source revisions
    Development update

    flyology_cachelines 0.1.1-dev

    2 updates: c2db3e42 through ef6841e7

    Cache-line-aware storage and cache information for Ada

    Manifest fields
    origin
    Show all 2 updates
    1. c2db3e42 updated to 159210caindex 23c79db9

      20 source commits

      1. df4d1837Add composable scoped I/O operations
      2. 9b8f71e8Preserve scoped file timeout semantics
      3. 69a526a8Queue scoped files under submission pressure
      4. a0190f51Make operation rearming transactional
      5. ed0d6fa9Add public operation continuations
      6. 00d106aaExpand scoped file lifecycle coverage
      7. 7c4b2523Add scoped datagram operations
      8. 28b228bbAdd scoped Internet connect operations
      9. 112761c7Add scoped Internet accept operations
      10. e0ab1878Add scoped Unix socket operations
      11. 624d33c5Add owned-buffer file operations
      12. cad92a77Add scoped file watcher operations
      13. 077a9641Add composable task result operations
      14. 66896e62Add composable bounded channel operations
      15. d01d358dAdd composable buffer channel operations
      16. 7b1e6b58Complete composable connection and watcher operations
      17. 3760634bAdd composable connection TLS upgrade
      18. 1810fc60Add set-independent connection driver capability
      19. 195b2289Add composable standalone TLS operations
      20. 159210ca
        Merge pull request #60 from flyology-ada/codex/composable-operations

        Add composable scoped operations across Flyology I/O

    2. 159210ca updated to ef6841e7index fe947caf

      1 source commit

      1. ef6841e7
        Problem: Recursive Alire discovery changes shared hashes

        Flyology's dependency pre-build runs nested alr printenv commands while the outer Alire action exports deployment-specific Flyology paths. Alire hashes those inherited values and can deploy the same release twice, then reject the conflicting generated prefix.

        Solution: Isolate nested toolchain discovery

        Scrub only Flyology's root, generated configuration, and generated prefix from both recursive printenv passes. Preserve the public manifest exports and toolchain fast paths, and cover compiler and GPRbuild discovery with a deterministic stale-environment regression.

    Compare source revisions
    Development update

    flyology_debug 0.1.1-dev

    2 updates: c2db3e42 through ef6841e7

    Bounded in-memory tracing and gauges for Ada

    Manifest fields
    origin
    Show all 2 updates
    1. c2db3e42 updated to 159210caindex 23c79db9

      20 source commits

      1. df4d1837Add composable scoped I/O operations
      2. 9b8f71e8Preserve scoped file timeout semantics
      3. 69a526a8Queue scoped files under submission pressure
      4. a0190f51Make operation rearming transactional
      5. ed0d6fa9Add public operation continuations
      6. 00d106aaExpand scoped file lifecycle coverage
      7. 7c4b2523Add scoped datagram operations
      8. 28b228bbAdd scoped Internet connect operations
      9. 112761c7Add scoped Internet accept operations
      10. e0ab1878Add scoped Unix socket operations
      11. 624d33c5Add owned-buffer file operations
      12. cad92a77Add scoped file watcher operations
      13. 077a9641Add composable task result operations
      14. 66896e62Add composable bounded channel operations
      15. d01d358dAdd composable buffer channel operations
      16. 7b1e6b58Complete composable connection and watcher operations
      17. 3760634bAdd composable connection TLS upgrade
      18. 1810fc60Add set-independent connection driver capability
      19. 195b2289Add composable standalone TLS operations
      20. 159210ca
        Merge pull request #60 from flyology-ada/codex/composable-operations

        Add composable scoped operations across Flyology I/O

    2. 159210ca updated to ef6841e7index fe947caf

      1 source commit

      1. ef6841e7
        Problem: Recursive Alire discovery changes shared hashes

        Flyology's dependency pre-build runs nested alr printenv commands while the outer Alire action exports deployment-specific Flyology paths. Alire hashes those inherited values and can deploy the same release twice, then reject the conflicting generated prefix.

        Solution: Isolate nested toolchain discovery

        Scrub only Flyology's root, generated configuration, and generated prefix from both recursive printenv passes. Preserve the public manifest exports and toolchain fast paths, and cover compiler and GPRbuild discovery with a deterministic stale-environment regression.

    Compare source revisions
    Development update

    flyology_numa 0.1.0-dev

    2 updates: c2db3e42 through ef6841e7

    Memory-node topology reporting for Ada

    Manifest fields
    origin
    Show all 2 updates
    1. c2db3e42 updated to 159210caindex 23c79db9

      20 source commits

      1. df4d1837Add composable scoped I/O operations
      2. 9b8f71e8Preserve scoped file timeout semantics
      3. 69a526a8Queue scoped files under submission pressure
      4. a0190f51Make operation rearming transactional
      5. ed0d6fa9Add public operation continuations
      6. 00d106aaExpand scoped file lifecycle coverage
      7. 7c4b2523Add scoped datagram operations
      8. 28b228bbAdd scoped Internet connect operations
      9. 112761c7Add scoped Internet accept operations
      10. e0ab1878Add scoped Unix socket operations
      11. 624d33c5Add owned-buffer file operations
      12. cad92a77Add scoped file watcher operations
      13. 077a9641Add composable task result operations
      14. 66896e62Add composable bounded channel operations
      15. d01d358dAdd composable buffer channel operations
      16. 7b1e6b58Complete composable connection and watcher operations
      17. 3760634bAdd composable connection TLS upgrade
      18. 1810fc60Add set-independent connection driver capability
      19. 195b2289Add composable standalone TLS operations
      20. 159210ca
        Merge pull request #60 from flyology-ada/codex/composable-operations

        Add composable scoped operations across Flyology I/O

    2. 159210ca updated to ef6841e7index fe947caf

      1 source commit

      1. ef6841e7
        Problem: Recursive Alire discovery changes shared hashes

        Flyology's dependency pre-build runs nested alr printenv commands while the outer Alire action exports deployment-specific Flyology paths. Alire hashes those inherited values and can deploy the same release twice, then reject the conflicting generated prefix.

        Solution: Isolate nested toolchain discovery

        Scrub only Flyology's root, generated configuration, and generated prefix from both recursive printenv passes. Preserve the public manifest exports and toolchain fast paths, and cover compiler and GPRbuild discovery with a deterministic stale-environment regression.

    Compare source revisions
  27. HTTP 0.1.2 is unavailable from the index

    a3c93cee on GitHub
  28. HTTP 0.1.1 is unavailable from the index (#12)

    40925f35 on GitHub
  29. Publish flyology_quic 0.1.1 (#11)

    4634a228 on GitHub
  30. Advance development source pins

    97a66ee7 on GitHub
  31. Development updates

    Development update

    flyology 0.1.1-dev

    6 updates: 91d6a0f6 through a53da35d

    Experimental GNAT runtime extension for native and lightweight Ada tasks

    Manifest fields
    depends-on, description, origin
    Show all 6 updates
    1. 91d6a0f6 updated to 9a24bf68index 510cfcf6

      39 source commits

      1. 40849230
        Problem: DNS smoke depends on hosted-runner timing

        The functional loopback checks use retry intervals too narrow for occasional macOS hosted-runner stalls. An early client exception also waits behind cancellation coordination and loses the operation that failed, leaving only a generic lifecycle assertion.

        Solution: tolerate stalls and report DNS smoke stages

        Use functional smoke deadlines that accommodate runner scheduling, let coordination observe early client completion, and report the execution model and operation stage for unexpected exceptions. The dedicated DNS resilience smoke retains narrow deadline coverage.

      2. 347604c6
        Problem: Codex and Claude usage across the Flyology workspace is difficult to audit

        Session logs are distributed across project checkouts, worktrees, sister
        repositories, and nested agent sessions. Their token counters also contain
        cached input, repeated cumulative records, inherited history, and duplicated
        Claude message entries, making straightforward aggregation inaccurate.

        Solution: add a portable incremental AI usage audit

        Add a self-contained PEP 723 Python script that discovers the workspace from
        its containing repository and scans associated Codex and Claude Code logs,
        including worktrees, subagents, and workflows.

        Deduplicate cumulative and inherited records, categorize base input, cache
        reads and writes, output and reasoning tokens, and estimate API-style costs
        using model-specific pricing. Persist JSON cursors and daily aggregates so
        subsequent runs process only new log records.

        Provide summary, daily, weekly, provider, and model breakdowns with JSON
        output, date filtering, configurable paths and timezone, state rebuilding,
        and integrity diagnostics.

      3. 73925055
        Problem: Flyology website presents Runtime as the umbrella

        The landing page, navigation, guide index, and machine-readable documentation center Flyology Runtime while standalone libraries share the project identity without depending on it. Visitors cannot reliably distinguish the runtime core, runtime-dependent protocol libraries, and independently adoptable components, and several component documentation paths are missing or placed under the wrong section.

        Solution: Present Flyology as the project and Runtime as its core

        Reorganize the landing page around the project umbrella, add focused Runtime and Libraries pages, move Guide, Architecture, and the main API under Runtime, separate standalone documentation from the Runtime guide, link each published component Guide and API, fix the scrollable guide topic rail, and align README, product, design, journal, build assertions, and llms.txt with the same dependency model.

      4. 6cb6887f
        Problem: Flyology package discovery and maturity guidance compete

        The redesigned project pages repeat the experimental label in several nearby locations while the curated Libraries directory has no path to the complete package index. Readers see redundant maturity warnings but cannot easily reach version, dependency, availability, and compiler-build records for every published package.

        Solution: Clarify maturity guidance and link the complete crate index

        Keep experimental status in the primary explanatory context, make constraints and adoption guidance more direct, and link crates.flyology.org from the Libraries introduction, footer, and llms.txt documentation map.

      5. 4738d656
        Problem: The crate index is absent from shared site footers

        Only the Libraries page exposes the complete package catalogue in its footer. Readers arriving on Runtime, Guide, Architecture, Journal, or the project overview have no equivalent utility path to package versions, dependencies, and availability records.

        Solution: Add the crate index to every shared footer

        Place the Crate index utility link first in each hand-written footer, including the journal entry template, while retaining every page-specific navigation link.

      6. 5b7c3925
        Problem: Cancellation promptness is asserted as a per-round wall-clock bound

        Check_Parent_Cancellation_Is_Prompt in tests/task_scope_faults_smoke requires
        every one of 16 rounds to propagate parent cancellation within 5 ms.
        Propagation crosses two lightweight-task wakes, and a contended shared runner
        can deschedule either of them for milliseconds, so the check reports host
        scheduling as often as it reports the mechanism. CI run 32100324387 failed
        this assertion on its first attempt and passed on a rerun of the identical
        commit 71df9ed, whose only change is .github/workflows/pages.yml. Locally,
        96 spinning processes on 16 cores plus nice -n 20 reproduce the failure in
        2 of 30 runs, and 1280 rounds measured under that load put the median at
        78 us with 0.9 per cent of rounds past 5 ms: the mechanism is prompt and the
        bound is reporting the host. A bare pragma Assert also names only a source
        line, so a real regression is indistinguishable from a stalled round.

        Solution: Require most rounds to be prompt, bound the rest, and report them

        The check now measures all 16 rounds, requires at least 10 of them within
        1 ms, and requires no round past a 0.5 s sanity ceiling. That is a stronger
        claim about the mechanism rather than a weaker one. The retired 10 ms polling
        monitor spreads its latency across its period and places about 1.6 of 16
        rounds inside 1 ms, so it clears the new bar about once in two million runs
        against once in sixty-five thousand for the old whole-round 5 ms bound;
        reinstating that monitor put 0 of 16 rounds inside 1 ms and failed the new
        check on all five idle runs. Under the load that failed the old check in
        11 per cent of runs, the new check passed 60 of 60. A failing round set is
        printed to standard error so the next failure names the rounds and their
        latencies instead of only the assertion line.

      7. 857820c4
        Merge pull request #47 from flyology-ada/claude/gifted-sanderson-75002d

        Problem: Cancellation promptness is asserted as a per-round wall-clock bound

      8. 5dfa0d25
        Problem: Broken site links reach main before anything checks them

        The site check that validates local links and fragment targets runs only in
        the Pages workflow, which triggers on a push to main and on manual dispatch.
        No pull-request workflow builds the site, and ci.yml has no site job, so a
        change that breaks a link passes every check a reviewer sees, merges, and
        then fails the Pages build on main. The site stops publishing at the point
        where the mistake is hardest to attribute.

        The hand-written pages carry 457 links into generated GNATdoc entries across
        eleven guide and architecture pages. GNATdoc names each entry by a hash of
        the declaration, so changing a public subprogram's parameters gives it a new
        anchor and silently strands every hand-written link to it. Editing the
        surrounding documentation comment does not, which makes the failure easy to
        miss: prose edits are safe, and a signature change quietly is not.

        Solution: Build and check the site on pull requests

        The Pages workflow now also runs on pull_request. The build job is
        unchanged for a push, and on a pull request it builds the site and runs the
        same link check without touching Pages: configuring Pages, uploading the
        artifact, and the deploy job are all skipped. A pull request therefore needs
        no Pages permission, which also keeps the job usable from a fork.

        Concurrency now groups per ref. One group for every event serialized
        unrelated pull requests behind each other and behind a deploy. Pushes to main
        still share one group and are still never cancelled; a pull request cancels
        its own superseded runs.

        This adds a toolchain and GNATdoc build to each pull request, which is the
        cost of resolving generated anchors: the check can only confirm a fragment
        exists by generating the page that defines it.

        Checks run: the workflow parses, has no tabs, guards exactly the three
        Pages-specific steps, and keeps the link check unguarded. check-site.mjs was
        confirmed to catch this class of breakage against a page carrying one stale
        API fragment, where it reports "missing fragment target" and exits non-zero.
        This pull request triggers the new job, so its own run is the end-to-end
        check.

      9. 252f4fd7
        Problem: Ada programs cannot see the host's memory-node structure

        A machine with more than one processor package attaches memory to each of
        them, and memory attached to the package a thread runs on is reached faster
        than memory attached to another. Nothing in this repository reports that
        structure. Ada itself does not describe it either: System.Multiprocessors
        covers processors and dispatching, and the language has no notion of a
        memory node at all.

        Without it, a program that wants its work near its memory has nothing to
        place against.

        Solution: Adopt flyology_numa as a nested standalone crate that reports it

        The crate reads the host description and reports memory nodes, the
        processors attached to each, firmware-declared distances, per-node memory,
        and processor packages. It does not place memory; that is a separate
        question this crate does not answer.

        Three decisions shape the interface.

        Topology queries are total. A host with no memory-node structure reports one
        node holding every processor, because such a host genuinely has one memory
        domain. Support distinguishes a description that was read from the host from
        that single-domain description. Individual facts a host does not answer use
        the existing variant-record convention with Value_Or, so a caller names its
        own fallback rather than receiving a plausible number.

        Online and permitted nodes are reported separately. A container is shown the
        whole machine's node list while a control group restricts what it may
        allocate on, so the host description alone does not establish permission.
        Allowed_Nodes intersects the description with Mems_allowed_list from the
        process status file.

        Node and processor numbers are the host's own, and sparse. They match sysfs
        paths and numactl output, so a reported number is the number to look up
        elsewhere. To_CPU performs the Ada processor mapping GNAT applies unchecked,
        and declines when the host's numbering has a gap the mapping cannot carry.

        A description this crate cannot read is reported as a shortfall rather than
        guessed at. Support.Complete goes false when any part of the description was
        refused: a node or processor number beyond the represented range, a list
        naming more ranges than the reader holds, an unreadable processor list, or a
        permitted-node list the host named and the reader did not understand. The
        distinction that matters is between a node with no processor attached, which
        is an ordinary memory expander, and a node whose processor list could not be
        read, which is not known to have none. A description that names nodes but
        attaches no processor to any of them is refused outright, because every
        machine has a processor.

        The sysfs reader names the directories it reads instead of assuming them, so
        it is host-independent text processing that compiles and runs everywhere.
        This departs from flyology_cachelines, which keeps all Linux code under a
        Linux source directory and tests only the host it runs on. The interesting
        cases cannot be reached that way: a development machine has one node and a
        container on one is single-node too. Twelve recorded descriptions under
        tests/fixtures cover two packages of one node each, two packages each
        divided into two memory nodes, a node carrying memory with no processor
        attached, sparse node numbering, a control-group restriction, a gap in
        processor numbering, an older host naming only its ordinary memory, and five
        descriptions the reader must refuse or report as incomplete. All are
        exercised on macOS, which has none of them.

        Set algebra lives in its own unit rather than the root body because
        discovery runs during the root package's elaboration and cannot call back
        into the body it is elaborating. Each step of the discovery chain names the
        body it needs with pragma Elaborate, so the ordering does not rest on the
        binder inferring it. Elaborate_All would not serve: its closure reaches back
        through the platform spec to the root body itself.

        A processor list is bounded at one range per processor rather than at 64,
        because a host that enumerates processors round-robin across its nodes gives
        each node a list of single-processor ranges.

        Verified with ./flyology_numa/scripts/test.sh on macOS aarch64 from a clean
        tree: both the host suite and the fixture suite pass, and clean builds of
        the linux, macos, and unsupported platform bodies through the crate's
        host-selection scenario variable emit no warnings, style diagnostics, or
        errors.

      10. 376d2481
        Problem: Flyology_NUMA reports memory nodes but cannot use them

        The crate describes which memory nodes a host has and which processors are
        attached to each. A program that wants its work near its memory can read
        that and then do nothing with it: there is no way to ask that a region's
        pages be drawn from a chosen node.

        Solution: Add Flyology_NUMA.Placement over the kernel's memory-policy calls

        Placement is a separate package from the reporting one because the two fail
        differently. Reading a description always succeeds; acting on one often does
        not. Support reports which of three states applies before anything is
        attempted, and every operation reports its own outcome rather than raising.

        The third state is the one worth having. A host may have no placement
        interface, or it may have one this process is refused. A container sandbox
        commonly refuses these calls while the machine underneath has memory nodes
        that other processes are using, and reporting that as a host without the
        facility would be wrong. Denied is therefore distinct from Unsupported_Host.
        The two are told apart by what the host said about itself rather than by the
        error number alone, because a sandbox may answer a refused call by claiming
        the call does not exist: a host that described its own memory nodes has the
        calls that act on them, so a refusal from such a host is a denial.

        Support is settled on the first call that needs it rather than while the
        package elaborates. A sandbox that answers a refused call by ending the
        process would otherwise end any program that merely links this crate, even
        one that never places memory.

        Apply_To places a range, Apply_To_Thread places what the calling thread
        allocates from then on, Node_Of_Address reports where a page ended up, and
        Permitted_Nodes asks the host afresh rather than reusing what it said
        earlier. A range must begin on a page boundary because placement acts on
        whole pages; an unaligned range is refused before the host is asked.

        Three details of the kernel interface are easy to get wrong and silent when
        got wrong, so each is handled deliberately.

        The node-bit count is decremented by the kernel before the mask is read, so
        passing the number of bits meant would drop the highest node. Placement
        passes one more than that, which names every node this crate represents
        while still asking for only the eight bytes the mask has. Reading the
        permitted nodes is bounded differently again: the kernel refuses a count
        below the number of nodes the host could ever have, counting nodes that are
        merely possible rather than online, so that read uses a buffer covering the
        largest node count Linux can be built for.

        Two policies take no node set, and the kernel rejects either of them when
        one arrives. Passing the set a caller naturally has to hand would therefore
        fail, so the set is dropped before the host sees it and the interface's
        promise that it is ignored is kept.

        The preferred policy takes a single node, not a set. The interface documents
        that only the lowest-numbered node is preferred rather than implying the
        whole set contributes.

        No C library wraps these calls. Their manual pages document a separate
        library's wrappers, not the one every program already links, so they are
        reached through the generic system-call entry point. That entry point is
        variadic, which is one of the reasons this repository admits C, but GNAT's
        variadic convention reaches it correctly without a C file and keeps the
        crate free of one, as flyology_cachelines is.

        Call numbers differ per architecture, and not only in value: the x86-64
        table and the table newer architectures share disagree on the order of
        get_mempolicy and set_mempolicy. Calling by a number from the wrong table
        reaches a working but unrelated kernel service, which is worse than not
        calling at all, so each table is written out separately and an architecture
        whose numbers are not recorded disables placement rather than borrowing
        them.

        That failure is silent by nature, so the host suite has an invariant that
        exposes it: a host that described its own memory nodes has the calls that
        act on them, so reporting no way to place memory means the calls were not
        reached. Building for one architecture with another's table was checked to
        fail on exactly that assertion rather than passing quietly, and passing a
        node set with a policy that takes none was checked to fail before the set
        was dropped.

        Verified on macOS aarch64, x86-64 Linux, and AArch64 Linux. macOS reports
        Unsupported_Host and places nothing. Both Linux architectures report
        Supported and complete every operation: every policy applied to a range and
        to the calling thread, a written page reported on an online node, an
        unaligned range refused, and an empty node set refused for a policy that
        needs one. Builds of the macos, linux and unsupported platform bodies across
        x86-64, AArch64 and an architecture with no recorded table emit no warnings,
        style diagnostics, or errors.

      11. 41e2d423
        Problem: Naming a memory node for an object means placing it by hand

        Flyology_NUMA.Placement acts on an address range. Using it to put an object
        on a chosen node means obtaining page-aligned memory, placing it, carving
        objects out of it, and releasing it afterwards, all in the caller's code and
        all outside the language's own way of saying where memory comes from.

        Ada already has that way: the storage pool of an access type. Nothing here
        supplied one.

        Solution: Add Flyology_NUMA.Pools, a storage pool whose subpools are nodes

        An access type names the pool and each allocation names the node, so where
        an object lives is written at the point it is created rather than arranged
        around it:

        Item : constant Sample_Access := new (On_Node (Arena, Near)) Sample'(...);

        Subpools are the part of the language that fits this. A pool alone would fix
        the node when the access type was declared; a subpool is chosen per
        allocation, which is what naming a node needs to be.

        The pool obtains whole pages from the host rather than taking memory from
        the ordinary heap. Heap memory may begin partway into a page whose remainder
        belongs to something else, and placing that page would move memory this
        crate does not own. Pages are placed before any of them is handed out, since
        placing them afterwards would leave whatever had already been written where
        the host first put it.

        Memory is handed out by advancing through pages already obtained, and goes
        back to the host when a subpool is deallocated or the pool is finalized.
        Freeing a single object does nothing. That suits memory built up and
        discarded together, which is what a node-bound arena usually is, and the
        interface says so rather than implying a general allocator.

        Ownership of the pages is left to the runtime's own teardown rather than
        taken over. The runtime keeps the records it needs to finalize an object
        inside the very pages that object lives in, and a pool that gave its pages
        back first would take those records with them; a pool holding anything with
        finalization would then fail on the way out of its own scope. Deallocating
        one subpool likewise forgets it, because the runtime has already detached it
        by then and a pool that still believed it owned it could never serve that
        node again.

        Only the policies that name a node can be given to a pool. The two that name
        none place nothing on the node the subpool stands for, so a pool built on
        one would report memory placed there that never was.

        Placement_Reached separates a host that placed the memory from one that
        could not, and says which of the two it means: the host accepted the
        request. Under a bound policy that puts the pages on the node; under a
        preferred one the host stays free to draw from elsewhere. Allocation
        succeeds either way, on the reasoning that memory in the wrong place still
        runs while no memory does not.

        A pool is not task safe, and the interface says so. Two tasks allocating
        from one subpool at once can be handed the same address.

        Verified on macOS aarch64, x86-64 Linux, and AArch64 Linux, and inside
        guests built to have several memory nodes, which no machine to hand does.
        scripts/multinode-check.sh boots a two-node guest and a four-node guest
        whose distances are uneven and one of whose nodes carries memory with no
        processor attached, then runs the host suite inside them. It was run on
        both x86-64 and AArch64, each emulating its own architecture, so that the
        placement calls a guest makes are the ones its architecture's table names. Those runs are
        what exercise choosing between nodes at all: memory bound to each node in
        turn and confirmed held by that node, including the node with no processor;
        interleaving spread over every node rather than drawn from one; and a node
        shown further from another than from itself.

        The suite gained cases for the two failures described above, and each was
        confirmed to fail before the change and pass after. Builds of the macos,
        linux and unsupported platform bodies across x86-64, AArch64 and an
        architecture with no recorded placement table emit no warnings, style
        diagnostics, or errors.

      12. a416d8dc
        Problem: The flyology_numa test entry point is not executable

        ./scripts/test.sh runs each crate's own entry point by path, so the file
        has to carry the executable bit. flyology_numa/scripts/test.sh was recorded
        without it and the whole suite stopped there, reporting only that a command
        could not be run.

        Running the script as an argument to a shell, which is what a person does
        while writing one, works either way and hides this.

        Solution: Record the executable bit, as the other crates' entry points do

      13. 550bc612
        Problem: flyology_numa is absent from the site and the API reference

        The crate ships, and nothing outside its own directory says so. It has no
        guide page, no generated API reference, and no entry in the library ledger
        or the machine-readable index. A reader who finds the other standalone
        crates on the site does not find this one.

        Solution: Adopt the crate into the documentation and the site

        The crate now builds its own GNATdoc reference, and the root documentation
        run builds and asserts it alongside the other crates. Publishing it required
        documenting the pool primitives the runtime calls, which had no comments,
        and describing the pool's discriminants in prose: @field names a record
        component, and a discriminant of a private type is neither.

        The package renaming that shortened System.Storage_Pools.Subpools in the
        public part is now in the private part. GNATdoc reported the public renaming
        on every documentation run, and the full name appears twice in the visible
        declarations rather than in every generated page.

        The guide page follows the order a reader needs: add the crate, read the
        node structure, use the permitted nodes rather than the online ones, handle
        a host with one memory domain, place memory, allocate from a node, and read
        distances and packages for what they say rather than what they suggest.

        Every API link on that page was resolved through the generated search index
        rather than by reading the generated markup, which does not put an entity's
        name where a reader of the HTML would expect it.

        The library ledger keeps its alphabetical order, so the new entry is S05 and
        the two entries after it move up.

        Verified with ./scripts/docs.sh, which builds the reference with no
        undocumented-entity warnings, and ./scripts/build-site.sh followed by the
        site checker, which reports 144 HTML files and 201 total files. The crate's
        own suite still passes.

      14. ae1e3ddf
        Problem: The landing page does not list flyology_numa

        The project map in the hero names each standalone library, and the
        catalogue below it links each one. Both lists stop at the crates that
        existed before this one. A reader who arrives at the site and looks for what
        Flyology offers does not learn that the crate exists.

        Solution: Add the crate to the hero project map and the catalogue

        Both lists keep their alphabetical order, so the entry sits between IRI and
        SIMD. The catalogue entry links to the guide, as the entries for the other
        crates with a guide on this site do.

        Verified with ./scripts/build-site.sh and the site checker, and by fetching
        the built pages: the hero and catalogue both list the crate, and all 39
        internal links on its guide page resolve.

      15. aa8b12ed
        Problem: The numa guide explains how before it explains what

        The page opens with a short definition in a callout and then goes straight
        to adding the crate. A reader who does not already know what a memory node
        is learns the interface before the reason for it, and a reader who does know
        still gets no picture of the machine the crate describes.

        Solution: Open with a section that explains memory nodes and draws one

        The section states what changes when a machine has more than one processor
        package, draws a two-node machine with a local and a remote access, and says
        plainly when placement is worth doing at all: a program that fits in cache,
        or one that allocates little, does not gain from it. The callout it replaces
        said less.

        The diagram uses only the classes the figure context defines. An earlier
        draft used a class that context does not style, and SVG then fell back to a
        solid black fill. That reads as deliberate against a dark background and
        wrong against a light one, which is how it survived a first look.

        Both themes were checked by computed style rather than by eye. The
        containers take the page's own surface and border colours, so they follow
        the theme instead of fighting it.

        Verified with ./scripts/build-site.sh and the site checker.

      16. 7b70cbf6
        Problem: Allocation algorithms are coupled to Flyology shared-memory policy

        Buddy, best-fit, and TLSF live inside the main package hierarchy, so bare-board runtimes cannot reuse them without also accepting Flyology identity, mapping, and shared-memory concerns.

        Solution: Extract allocation algorithms into a standalone crate

        Add flyology_allocators 0.1.0-dev with caller-owned regions, timed contention retries, native and ARM bare-board verification, and optimized memory primitives. Keep magic and schema policy in a thin Flyology adapter, pin the new crate from Flyology, and update integration tests and documentation.

      17. 7bf86246
        Problem: Standalone allocator performance has no focused comparison

        The extracted algorithms lack a reproducible benchmark against the platform allocator, making hot-path regressions and algorithm tradeoffs difficult to measure.

        Solution: Add a dedicated flyology_bench allocator shootout

        Add an optional hosted benchmark subcrate with fixed-size and fragmented-churn workloads comparing malloc, Buddy, Best-Fit, and TLSF in balanced paired rounds. Keep benchmark dependencies outside the bare-board crate closure and document release and smoke workflows.

      18. be44ac54
        Problem: Buddy allocator repeats checked address work on every node

        Profiling shows recursive Buddy allocation and release spend most of their time rebuilding and validating structure-relative node addresses. Release also validates each handle twice before its first mutation, making small allocation cycles substantially slower than the other standalone algorithms.

        Solution: Cache the validated Buddy node-table binding

        Retain the process-local node-table base in the attached view after validating its complete native range, use bounded node-relative addressing on hot paths, clear the binding on detach, and remove the redundant release validation while preserving validation before mutation.

      19. 283d5e71
        Problem: TLSF repeats checked address work on every metadata field

        Profiles of fixed allocation cycles show TLSF spending most of its time in free-list insertion and removal, block initialization, and handle validation. Each logical operation repeatedly recomputes and validates the same block base before touching adjacent scalar fields, leaving the constant-time algorithm dominated by address machinery.

        Solution: Reuse validated block bases across TLSF hot paths

        Validate each referenced block extent once, carry its process-local base through list mutation, splitting, coalescing, and handle release, and keep stored link, size, generation, state, and bitmap checks intact. Avoid a redundant ready-state check while the arena guard is held and replace size-class division by its exact power-of-two shift.

      20. e9199d66
        Problem: Best-fit allocator repeats metadata work on hot paths

        Profiling shows fixed-layout address validation, duplicate split and coalesce writes, and repeated AVL balance reads dominate Best-Fit allocation and release. This leaves both fixed cycles and fragmented churn substantially slower than necessary.

        Solution: Streamline checked Best-Fit metadata operations

        Cache the last complete block-header location in the local view, use a fixed-field address path that retains attachment and complete-header bounds checks, avoid tree metadata writes that insertion immediately replaces, and compute AVL balance inputs once per ancestor. The stored layout, persisted validation, guard behavior, handle generations, and bare-board dependency boundary remain unchanged.

      21. 05d2eb83
        Problem: Allocator benchmarks leave imported algorithms unoptimized

        The benchmark project selects release switches only for its own sources. Imported flyology_allocators units are compiled without optimization, making comparisons against the optimized system malloc misleading and overstating allocator hot-path costs.

        Solution: Force a clean optimized benchmark closure

        Build the benchmark and all imported Ada sources through gprbuild with explicit O3, debug symbols, Ada 2022, warnings, and validity checks. Document why the runner must apply switches across project boundaries.

      22. 77e1d163
        Problem: Benchmark arrays use obsolete aggregate syntax

        GNAT reports parenthesized array aggregates as obsolescent when the benchmark closure is compiled as Ada 2022, obscuring useful build diagnostics.

        Solution: Adopt Ada 2022 bracketed array aggregates

        Convert Flyology Bench array initializers and expressions to bracket syntax while retaining parentheses for record aggregates. Keep the obsolescent warning category enabled so future occurrences remain visible.

      23. 77ce4c04
        Problem: TLSF eagerly coalesces every released block

        Release repeatedly discovers physical neighbors and removes and reinserts free-list entries even when the next allocation can reuse the same size class. This makes steady fixed-size and churn workloads pay fragmentation-recovery costs on every operation.

        Solution: Defer TLSF coalescing until allocation requires it

        Return released blocks directly to their size class and perform a bounded, checked physical coalescing pass only after a normal TLSF search misses or before destroying an empty arena. Preserve boundary tags and bitmap/list validation, and cover adjacent runs, allocated gaps, attachment, stale handles, and complete teardown with adversarial tests.

      24. 562bdd61
        Problem: TLSF still advertises eager constant-bound behavior

        Lazy coalescing makes worst-case allocation linear and no longer joins neighbors during release, but both capability records and package comments retain the eager algorithm contract. Flyology also reuses the eager persisted identity even though version 2 readers reject valid adjacent free blocks produced by the new implementation.

        Solution: Publish the lazy TLSF contract and identity

        Report the linear worst-case search and deferred release coalescing in standalone and Flyology packages, document the miss-triggered pass, and advance Flyology TLSF to version/schema 3 so cross-version attachment fails at the immutable header. Add standalone capability coverage and a Flyology regression that rejects the complete eager identity.

      25. 288b03a2
        Problem: Best-fit repeats split and merge work on exact reuse

        Profiling shows fixed-size allocation cycles spend most of their Best-Fit time splitting a large free block during allocation and immediately removing and coalescing its remainder during release. Fragmented churn repeats related AVL maintenance even when the same physical block can be reused directly.

        Solution: Defer Best-Fit coalescing until allocation needs it

        Index released blocks directly for exact-size reuse. Before reporting exhaustion, validate the complete physical chain, coalesce every adjacent free run, repair boundary links, and retry the AVL search. Accept the resulting persisted representation on attachment, canonicalize empty arenas during destruction, report the resulting linear worst-case search capability, and cover adjacent frees, alternating gaps, stale handles, attachment validation, and teardown.

      26. 41578832
        Problem: Flyology Best-Fit identity permits incompatible lazy images

        Deferred coalescing leaves adjacent free blocks as a valid persisted Best-Fit state. The earlier eager reader rejects that state, but Flyology still advertises the same outer version and schema, so compatibility fails only after entering nested allocator validation.

        Solution: Version the Flyology Best-Fit lazy invariant

        Advance the Flyology-only adapter version and schema while retaining its magic. This makes older readers reject lazy images at the outer identity boundary and keeps standalone allocator metadata free of application identity.

      27. ec813587
        Problem: Best-Fit identity transition lacks Flyology coverage

        The lazy Best-Fit adapter advances its persisted version and schema, but the Flyology data-structure smoke test neither proves rejection of the eager version-2 identity nor reflects the linear fallback and deferred-coalescing capabilities.

        Solution: Exercise the Best-Fit version-3 boundary

        Temporarily replace a live Best-Fit arena outer identity with the version-2 values and require attachment to fail closed, then restore the image. Assert the truthful lazy-coalescing capabilities for both Best-Fit and TLSF.

      28. e1315591
        Problem: Buddy eagerly rebuilds the same free hierarchy

        Small allocation cycles repeatedly collapse a released leaf to the root and split the same path on the next allocation. Profiling shows those release stores and recursive rebuilding dominate Buddy's fixed-size cost.

        Solution: Coalesce Buddy trees only when allocation needs it

        Keep released nodes in the retained split tree, compact free subtrees before a search reports genuine exhaustion, and compact before empty-arena destruction. Add adversarial coverage for half-tree and root reconstruction plus stale handles, and expose the lazy-coalescing capability accurately.

      29. 4ad89a24
        Problem: Lazy Buddy reuse still traverses the retained tree

        After deferring coalescing, profiling shows fixed-size Buddy allocation is dominated by walking the same split path. Fragmented churn also revisits released orders even though the releasing view already knows a suitable free node.

        Solution: Cache one validated free node per Buddy order

        Keep process-local node hints in each attached view, validate persisted state before every hinted reuse, and discard all hints during coalescing and detach. Preserve the persisted layout and fall back to the complete tree for stale or missing hints; cover stale hints across independently attached views.

      30. 22998f64
        Problem: Lazy Buddy metadata boundaries are incomplete

        Buddy still advertises logarithmic eager-coalescing behavior, an eager Flyology reader can attach a retained all-free split tree and falsely report exhaustion for a parent-sized request, and Destroy may release its guard after a partially failed coalescing pass without poisoning the image.

        Solution: Harden lazy Buddy capabilities and lifecycle handling

        Advertise linear miss search and deferred coalescing, advance only Flyology's outer Buddy identity to version 3, and verify the retained two-leaf compatibility case. Check that an arena is empty before Destroy mutates it and poison any coalescing failure. Compile the standalone project as Ada 2022 for bracket aggregates and extend standalone and Flyology compatibility tests.

      31. 66888189
        Problem: Allocator guides still describe eager coalescing

        Buddy, Best-Fit, and TLSF now defer coalescing until an allocation miss, but the root, standalone, and website guides still advertise their former fast-path and worst-case behavior. The stale prose also describes a process-shared guard even though the standalone algorithms are usable with arbitrary caller-owned storage.

        Solution: Document lazy coalescing and view-scoped state

        Describe each successful lookup and miss-triggered coalescing path, report the resulting linear worst-case bound, and use attached-view terminology. Record that stored geometry remains stable while the valid state contract changes and Flyology adapters use version-3 identities.

      32. 94cd5b57
        Problem: Lazy allocator correctness lacks an executable model

        Buddy, Best-Fit, and TLSF now retain free structure on release and coalesce on allocation misses. Behavioral tests cover examples, but no bounded state-machine review checks shared guard ownership, block partitions, index publication, stale view hints, generation-stamped release, false exhaustion, or operation completion across interleavings.

        Solution: Model guarded allocator transitions in TLA+

        Add a parameterized extraction for the three algorithms with policy-specific splitting and selection, TLSF bin and bitmap state, Buddy view-local hints, lazy coalescing, retry, generations, and fairness. Add safe TLC configurations plus required false-exhaustion, stale-hint, stale-bitmap, stale-release, and nontermination counterexamples, wire them into the authoritative runner, and document the production mapping and abstraction limits.

      33. 4dc3e5c0
        Problem: Allocator models can drift from Ada transitions

        The bounded Buddy, Best-Fit, and TLSF models establish safety and liveness for their extraction, but review alone does not detect when persisted metadata, view-local hints, generations, handles, or size-class computations diverge from the standalone kernels.

        Solution: Compare canonical Ada and TLC allocator traces

        Add test-only private-state observers and bounded public-operation traces for all three kernels. Model the same traces in TLA+, compare every operation-boundary snapshot byte-for-byte in the authoritative runner, require no-retry liveness counterexamples, and run the conformance boundary in CI while retaining standalone ARM cross-build isolation.

      34. 54d77f0f
        Problem: allocators lack a slab and span policy

        Solution: add a standalone bitmap-slab and contiguous-span allocator, bridge it into Flyology, benchmark it against the existing policies and malloc, and cover its bounded state machine with positive and deliberately broken TLA+ configurations.

      35. 239aa004
        Problem: slab slot reuse lacks a publication edge

        Solution: publish the affected 32-bit bitmap word with release ordering and acquire it before validating the slot generation. Add bounded safe and deliberately broken TLA+ visibility models so TLC reproduces the former stale-handle acceptance.

      36. 195b83bf
        Problem: large span validation trusts the head extent

        Solution: add a corruption test that makes one large-span head claim its neighboring live allocation, then validate every head and tail descriptor field before reporting capacity or allowing release to mutate the claimed extent.

      37. 7a7bc16f
        Problem: The site does not list flyology_allocators

        The hero project map, the standalone catalogue, the library ledger, and
        llms.txt each name every standalone crate. This branch adds a new one, and
        all four lists stop at the crates that existed when the branch was written.
        A reader who arrives at the site and looks for what Flyology offers does not
        learn that the crate exists.

        Solution: Add the crate to the hero map, catalogue, ledger, and llms.txt

        Every list keeps its alphabetical order, so the entry sits first among the
        standalone crates and the ledger indices shift from S01..S07 to S02..S08.

        The crate publishes neither a guide page on this site nor a generated API,
        because scripts/docs.sh does not build one and flyology.gpr excludes the
        crate from documentation. The entries therefore link to the source tree
        only, as the Flyology QUIC entry already does for the same reason. Adding an
        api/flyology_allocators/ link would fail the site checker.

        Verified with ./scripts/build-site.sh and the site checker, which passes on
        141 HTML files, and by grepping the built pages: the hero, catalogue,
        ledger, and llms.txt all name the crate.

      38. 7dc419f2
        Problem: The data-structures guide links to pages GNATdoc no longer emits

        This branch turns Allocation_Algorithms.Buddy, Best_Fit, and TLSF from
        documented packages into generic instantiations of Allocation_Algorithms
        .Contract. GNATdoc emits no unit page and no declaration anchor for an
        instantiation, so the three API links the guide carries for them now resolve
        to nothing. main gained a site link checker after this branch was written,
        so the Pages workflow reports all three and fails.

        Solution: Present the three instantiations as code rather than links

        AGENTS.md asks that the first explanatory mention of a public entity link to
        its verified generated GNATdoc unit or declaration entry. No entry is
        generated for these three, so there is nothing to link, and pointing them at
        the kernels or at Contract would name a different entity than the prose
        does. The surrounding Arenas, Contract, Allocation_Capabilities, and View
        links are unaffected and still resolve.

        Verified with ./scripts/build-site.sh and the site checker, which now passes
        on 141 HTML files and 198 total files with zero problems.

      39. 9a24bf68
        Problem: The data-structures guide omits the slab/span allocator

        This branch adds Allocation_Algorithms.Slab_Span as a fourth arena allocator
        and says so in the README, but the guide section that tells a reader how to
        choose one still presents three. It names three adapters, describes three
        policies, gives three decision rows, and twice states that all three share
        one metadata guard. A reader choosing an allocator from this page does not
        learn the fourth exists, and the two counts now contradict the README.

        Solution: Describe slab/span alongside the other three and correct the counts

        The introductory paragraph names the adapter and states its shape: bitmap
        slots in fixed runs for small requests, contiguous runs for larger ones, with
        descriptors and generation tables outside the managed bytes. A decision row
        gives the selection rule and the reclamation behavior a caller can observe:
        requests up to half the configured run size take a generation-stamped slot,
        larger requests reserve whole runs, release keeps an emptied slab indexed for
        reuse, and a miss reclaims empty slabs to obtain the run or span it needs.

        The row also states that the run size is an allocator quantum rather than an
        operating-system page, because the name invites the opposite assumption.

        The half-run threshold matches the kernel, which sends a request to a slab
        class when Requested <= Run_Size / 2 and to a span otherwise. Both "all
        three" counts become four. The adapter is a generic instantiation, so like
        Buddy, Best_Fit, and TLSF it has no generated GNATdoc entry to link.

        Verified with ./scripts/build-site.sh and the site checker, which passes on
        141 HTML files and 198 total files, and by parsing the built page: tags
        balance and the new row renders between TLSF and the compile-time choice.

    2. 9a24bf68 updated to 60de2c69index 8a8e9de5

      1 source commit

      1. 60de2c69
        Problem: A development pin ships in the published manifest

        flyology.gpr imports flyology_allocators.gpr, and the manifest both declares
        flyology_allocators as a dependency and pins it to the in-repo directory.
        Alire honours pins only in a root crate's manifest, so a consumer resolving
        flyology from the index never receives that dependency. Its solution omits
        flyology_allocators entirely and gprbuild then fails with "imported project
        file flyology_allocators.gpr not found". A crate whose only dependency is
        flyology = "~0.1.1-dev" reproduces it in two lines.

        Nothing in this repository reports the fault, because the pin satisfies the
        dependency for every build performed here. The pin also hid two further
        assumptions that only the in-repo directory could satisfy.

        Solution: Resolve the allocators dependency from the index

        Drop the pin so the declared dependency resolves the same way for this crate
        and for its consumers. The published flyology_allocators 0.1.0-dev is built
        from this repository at the same commit and the same subdirectory, so the
        source reached is identical; only the path by which it is reached changes.

        Configure the organization index in this repository's own workflows. They
        carried the community index alone, because the pin meant no job here ever
        resolved flyology_allocators from an index, and it is published only in the
        organization index. Without that step alr reports an incomplete solution
        naming flyology_allocators as missing.

        Name the excluded documentation project through the imported project rather
        than through a repository path. Documentation.Excluded_Project_Files listed
        flyology_allocators/flyology_allocators.gpr, which resolved only while the
        crate sat in this working tree; as a dependency its project lives in the
        Alire build tree under a content hash. Flyology_Allocators'Project_Dir asks
        the imported project where it is, so the exclusion holds wherever the
        dependency is deployed and the allocator packages stay out of this crate's
        generated API, where they would otherwise be documented twice.

        Record the rule that produced the fault in the agent guide: no committed
        pins in a crate manifest, alr pin in the consuming workspace for unpublished
        work, and a declared dependency must resolve from the index. Name the
        gprbuild error there too, since that is where the fault appears and it names
        a project file rather than a crate.

    3. 60de2c69 updated to 60de2c69index 28a2302d
    4. 60de2c69 updated to 9782c81bindex 75a836be

      16 source commits

      1. aeb10612
        Problem: The site does not list Flyology RDF

        The hero project map, the standalone catalogue, the library ledger, and
        llms.txt each name every component. Flyology RDF publishes a website, a
        guide, and three generated API references at rdf.flyology.org, but the name
        appears nowhere in this repository. A reader who arrives at the site and
        looks for what Flyology offers does not learn that the project exists.

        Solution: Add the project to the hero map, catalogue, ledger, and llms.txt

        flyology_rdf depends on flyology_iri only. It needs no runtime preparation
        and starts no tasks, so it belongs with the standalone libraries. Every list
        keeps its alphabetical order, so the entry sits between Flyology NUMA and
        Flyology SIMD and the ledger indices shift from S07..S08 to S08..S09.

        The ledger and llms.txt entries carry all three generated references, as the
        Flyology Postgres entries already do, because the project site treats the
        Notation3 and SPARQL APIs as first-class navigation.

        The llms.txt project-structure summary also omitted Flyology Allocators and
        Flyology NUMA, which the same file already listed further down. Both names
        join the summary here.

        Verified with the website-kit site checker, whose output is unchanged from
        the pre-change baseline, and by rendering the pages: the hero, catalogue,
        and ledger all name the project. The six linked URLs return 200.

      2. 2188ee0d
        Problem: The project map announces its framing and then hides the components

        The figure caption claimed "One project, two adoption paths" above two cards
        that already carry the same fact in their labels, so the caption restated
        what the diagram shows. The two card subtitles were not parallel either:
        "Core component" named a role while "No runtime dependency" named a
        dependency, so neither pair member helped a reader compare the paths.

        The component names below them were plain list items. A reader who found the
        name that matched the problem had no way to reach the component from the
        diagram and had to scroll to the catalogue to find the same name again.

        Solution: Drop the caption, make the subtitles parallel, and link the names

        The subtitles now read "Prepare the runtime" and "Add a crate", which state
        the two adoption paths as the actions they are. The figure keeps an
        accessible name through aria-label, and the figcaption rule leaves the
        stylesheet with the element it styled.

        Each component name becomes a link to its best available destination, which
        is the destination the catalogue below already uses: the project site where
        one exists, then the guide, then the generated API, then the source tree.
        The pill moves from the list item to the anchor so the whole badge is the
        hit target. Links open in a new tab and carry no underline, as requested, so
        hover brightens the border and adds a faint fill instead. Each list states
        the new-tab behavior once in its aria-label rather than repeating it in
        twelve hidden spans.

        Verified by rendering the page: every badge computes text-decoration-line
        none and cursor pointer, and the hovered badge is distinguishable from its
        neighbors. The site checker reports one new line against the baseline,
        api/flyology_debug/ from the new Debug badge, which resolves once
        scripts/docs.sh generates the GNATdoc output that this partial build omits.

      3. 5dfd5d36
        Problem: Nothing coordinates tools that need exclusive CPU capacity

        Two measurement runs that share a machine produce two wrong answers, and
        neither run can tell that it happened. The problem is not confined to
        benchmarks: a load generator, a soak test, or a profiler makes the machine
        loud, and a benchmark needs it quiet. Both want the same thing from opposite
        directions, and nothing lets them find each other.

        Worse, two runs that each suspend collection when they detect interference
        are symmetric controllers observing each other. Each pauses because the other
        is loading the machine, both then observe quiet, both resume together, and
        both immediately pause again.

        Solution: Specify a host CPU lock convention and implement it

        The convention is named for the resource rather than for benchmarking, so
        that the tools which create load take the same claim as the tools which need
        its absence. Conflict detection is flock and nothing else: liveness is the
        lock itself, so a holder that dies releases with no cleanup path, no stale
        registry entries, and no pid-reuse hazard.

        A machine-wide claim takes LOCK_EX on the claim file; a claim on individual
        CPUs takes LOCK_SH there and LOCK_EX on one file per CPU. Disjoint core-scoped
        claims therefore proceed concurrently while a machine-wide claim excludes them
        all, with no registry and no arbiter. Per-CPU claims are acquired in ascending
        order, because a total order is what stops two callers with overlapping sets
        from deadlocking on each other's partial claims.

        The path is a single deterministic default rather than a writability-probing
        fallback chain. A chain reintroduces the failure it was meant to prevent:
        /run/lock is 1777 on Debian and root-owned 0755 on Red Hat derivatives, so a
        root process and an unprivileged process on one machine would probe
        differently, land on different files, and each conclude it holds the machine.
        $TMPDIR is avoided for the same reason, being per-user on macOS.

        File content is diagnostic and is never consulted to decide conflicts. It is
        still specified and parseable, one key=value pair per line, because a reader
        must be able to name the holder; cwd is included because tool and pid alone do
        not distinguish one checkout or CI workspace from another. Readers open the
        file without locking, since a shared lock would block behind the very holder
        they are trying to identify, and must tolerate content that is empty, stale,
        or half-written.

        A claim is not proof of exclusivity, and the implementation does not present
        it as one. systemd PrivateTmp= bind-mounts a per-service directory over /tmp,
        so two services share every CPU and cannot see each other's claim files; that
        case is detected from /proc/self/mountinfo and reported as namespace-scoped.
        Separate containers are not detectable from inside and need an explicit shared
        path. A path can be proven private but never proven machine-wide.

        Only the C macros live in the native unit. GNAT's C_Variadic_2 convention
        calls open() correctly even on Darwin/AArch64, where variadic arguments are
        passed differently from fixed ones, so the protocol, the file grammar, and the
        /proc reader are all Ada. The convention compiles on every GNAT this crate
        supports, checked against 13.2.2 through 16.1.0 against an alire.toml floor of
        13, so no compatibility shim is carried.

        Verified by building the crate, and by taking claims on disk: the file matches
        the published grammar, parses with awk -F=, is created 0666, and per-CPU files
        are named beside the machine file.

      4. 13b71a5b
        Problem: The CPU gate only proves the host was quiet before warmup

        CPU_Quiescence samples host counters once, before clock characterization, and
        then never looks again. A machine that goes busy halfway through collection
        produces a result that reads as clean, and nothing in the measurement, the
        console card, or the machine-readable output says otherwise. The gate's own
        documentation admits it "cannot prevent new load from arriving after
        collection begins", and until now that was the end of the story.

        The obvious repair is not available either. Host utilization cannot simply be
        compared against a limit during collection the way the preflight does it,
        because by then the benchmark thread saturates a core and every sample would
        trip the limit.

        Solution: Watch for foreign load during collection and say what was found

        Foreign load is host busy time minus this process's own CPU time, so load the
        benchmark itself creates is correctly not foreign. The estimate scales the
        host busy ratio by wall time rather than converting ticks, so the platform
        tick length never enters the arithmetic. Cross-checked against top on a loaded
        machine, the two agree to within 0.1 percent.

        Three responses form a ladder. Observe records and keeps everything. Retake
        discards the contaminated window and collects it again. Pause waits for the
        host to settle, re-warms, and then collects it again. The re-warm is not
        politeness: a resumed run has cold caches, predictors, and frequency state, so
        without it the first sample after a pause is the outlier the pause existed to
        avoid.

        Nothing adjusts a reported statistic. A skew factor derived from observed load
        would be invented data, because the cost of interference depends on whether
        the contention is an SMT sibling, a shared cache, memory bandwidth, or another
        socket, and the same foreign share can mean no slowdown or a large one. Runs
        are annotated or repaired, never corrected.

        Observation happens between timed samples over windows of whole collection
        units, where a unit is one sample, one comparison pair, or one balanced
        multi-way round. A response therefore never splits the two halves of a pair
        and never lands mid-round, where it would spread interference unevenly across
        the cases a round exists to compare fairly. Windows carry a margin over the
        configured minimum: sized to only just reach it, ordinary batch jitter drops
        them below it and they silently degrade to observation. Host counters are
        tick-based, so a window that still falls short is recorded but never acted on.

        Discarding a window rolls back what the window changed. Per-sample values are
        written by index and survive a retake intact, but the position tally of a
        comparison pair and the process-telemetry summaries are running sums, so a
        discarded pass gives them back. Without that, a run with eighteen retained
        samples and twenty-four retakes would report elapsed time and an average CPU
        share covering forty-two samples, most of which were thrown away.

        Budgets degrade rather than abort. An exhausted retake or pause budget
        continues under Observe and reports it, and paused time is excluded from
        Maximum_Sampling_Time because waiting for the host is not collection.

        Placement is optional and sharpens attribution: with a strict binding every
        other CPU's busy time is foreign outright, and the placed CPU's share is its
        busy time minus the placed thread's own. SMT siblings join the watched set,
        because a process saturating the sibling of the placed CPU slows the
        measurement while leaving the placed CPU's own share clean, which makes
        sibling-blind core-scoped observation worse than host-wide observation rather
        than better. Placement is Linux-only in practice; Apple Silicon implements no
        thread affinity and rejects every request, so the Host_Control documentation
        no longer describes Darwin placement as merely advisory.

        Placement binds only the calling thread, so another thread of this process can
        occupy a watched CPU, where its time is indistinguishable from foreign load.
        Each window therefore reads process CPU as well as thread CPU, and their
        difference bounds how much of the watched capacity those threads could account
        for. Once that bound exceeds the configured foreign limit, the core-scoped
        answer can no longer address the question the limit asks: the run drops to
        host-wide observation, which is well defined for a multi-threaded process, and
        reports Attribution_Diluted. Otherwise a scheduler benchmark run under
        placement would spend its retake budget discarding samples over load it
        created itself. The window that reveals the dilution is discarded rather than
        recorded, because its value was computed under the attribution being
        abandoned.

        The direction of that fallback is deliberate. Core-scoped attribution
        subtracts only the placed thread, which over-reports interference when other
        threads share the watched CPUs; subtracting the whole process instead would
        deduct time our threads spent on CPUs outside the watched set, under-report
        foreign load, and let contaminated data pass as clean. Over-reporting shows up
        in the retake and contamination counts; under-reporting shows up nowhere.

        The host CPU claim is taken before the preflight gate, since waiting for a
        quiet host and then blocking on the claim leaves the quiet verdict stale.

        Everything observed reaches the console card, the CSV schema, and the JSON
        object. That visibility is the point: a run that had to repair itself must say
        so, or a heavily repaired result reads as a quieter machine than the one it
        ran on.

        Verified with ./scripts/test.sh on Darwin/aarch64 and in an Ubuntu 24.04
        container on Linux/aarch64, and under qemu-system-aarch64 across four CPU
        topologies. Core-scoped attribution asserts that it closed an observation
        window, so the thread-CPU probe it depends on cannot fail silently. Two
        assertions were checked against builds that defeat them: one with sibling
        collection disabled fails the sibling assertion under cores=2,threads=2 and
        passes without SMT, and one with the dilution check disabled fails the
        fallback assertion while a task of the test's own process burns CPU. Retake
        and pause are driven by a spawned process, because load raised inside this
        process is its own CPU time and is subtracted by design.

      5. 845bdaca
        Problem: The new guide section ignores the site's writing rules

        website/AGENTS.md governs hand-written pages under guide/**. The interference
        section met none of its API-link requirements and several of its style rules.

        Every public entity it introduced went unlinked: Interference, Placement,
        Host_Lock, the three Interference_Response literals, Maximum_Retakes, Window,
        Rewarm_Time, Maximum_Foreign_CPU_Percent, Include_Siblings, Require_Strict,
        Attribution_Diluted, and Environment. The same page already links
        CPU_Quiescence, Stable_Time, and Timeout, so the new section also read
        inconsistently against its own neighbours.

        Solution: Link the API entities and apply the three prescribed reviews

        The three reviews ran in sequence and are labelled here, since separate review
        agents were unavailable.

        Technical. "Foreign load is host busy time minus this process's own CPU time"
        held only without placement, because core-scoped attribution subtracts the
        placed thread rather than the whole process; the sentence now says so, and the
        placement paragraph states which CPUs the harness measures. "The re-warm is
        required" overstated a configurable field, so the text names Rewarm_Time and
        says what a zero value leaves behind. "When the difference exceeds the
        configured limit" named neither the limit nor the compared quantity, which
        also left Maximum_Foreign_CPU_Percent unlinked. Two harnesses that both pause
        do not deadlock as claimed; they alternate between pausing and resuming.

        Editorial. "This matters most" and "Without it" both referred back to
        something unnamed. Both now name their subject.

        Controlled language. "Sharpens attribution" was figurative and is now
        "narrows attribution to the placed CPU and its SMT siblings". "A run that
        repaired itself reports that fact" personified the run; the report is the
        actor, and it states counts.

        Verified with ./scripts/build-site.sh and the site checker, which passes 144
        HTML files. All fourteen API links resolve to an existing anchor in the
        generated GNATdoc output, and each target matches the entry the API search
        index gives for that entity. No sentence in the section exceeds the 25-word
        review signal.

      6. edf788ef
        Problem: The guide does not say the host controls are opt-in

        The interference section described three capabilities without saying that a
        run acquires none of them unless it asks. BENCH 07 states that contract for
        the preflight gate, and the page marks the default value of a choice where one
        exists, as it does for Equal_Time and Balanced_Rounds. The new section did
        neither, so a reader could not tell that enabling the watch alone changes
        nothing about the collected data.

        The claim file was also absent. The page named three environment variables but
        not the one path that other tools must agree on, leaving the coordination
        surface a click away in the convention document.

        Solution: State the defaults, the claim path, and the budget interaction

        Observe is now marked as the default response, in the form the page already
        uses. The closing paragraph mirrors BENCH 07: the watch, placement, and the
        host claim are disabled by default, so an existing run acquires no new wait or
        failure condition. The opening sentence calls the watch optional where the
        reader first meets it.

        The claim paragraph names /tmp/host-cpu.lock, the Path field that overrides it
        for one run, and the HOST_CPU_LOCK_PATH variable that overrides it for every
        tool following the convention. An earlier draft named only the variable, which
        implied it was the sole override; the technical review caught that against
        Resolved_Path and Try_Acquire.

        The Window row gains the limit that qualifies it. A window covers whole units,
        so a window spanning many short samples can exceed Maximum_Retakes on its
        first discard. Collection then continues under Observe and reports the
        exhausted budget, which otherwise looks like the response never ran.

        Numeric field defaults are deliberately not repeated here. No other section of
        the page tabulates them, every field now links to its generated entry, and a
        duplicated value is one that can go stale.

        Verified with ./scripts/build-site.sh and the site checker, which passes 144
        HTML files. All fifteen API links resolve to an existing anchor, and each
        target matches the entry the API search index gives for that entity, including
        the ambiguous Path simple name, which resolves to Host_Lock_Policy.Path. No
        sentence in the section exceeds the 25-word review signal, and no entity is
        linked twice.

      7. 4fbe5020
        Problem: The recording smoke test separates its workloads with a delay

        recording_smoke drives two benchmarks from four tasks and asserts that the
        slow benchmark's recorded median wall time exceeds the fast one's. The
        separation comes from delay 0.000_2 against delay 0.000_8. A relative delay
        is rounded up to the host timer tick, and on a Linux kernel with a coarse
        tick both requests wake at the same boundary near 3 ms. A four-task probe
        with no recorder involved shows the first iteration of each task honoring
        the request and every later one landing on the same plateau:

        0.0002 s: 323 3710 2829 2972 3069 2947 ... (us)
        0.0008 s: 1167 3307 2482 3625 2793 3045 ... (us)

        The two recorded medians then arrive at 2.98 ms and 2.99 ms, ordered by
        scheduling noise alone. On Ubuntu 24.04 with GNAT 16.1.0 on aarch64 the
        assertion fails about half the time: 9 of 20 runs on a clean checkout. macOS
        resolves the two delays apart, which is why the test has held there. The
        independent comparison checked two assertions below rests on the same
        separation and fails with it.

        Solution: Separate the distributions by work the workers perform

        Each worker spins a volatile rotate-and-xor accumulator, 20_000 rounds for
        the fast benchmark and twenty times that for the slow one, the idiom the
        file's concurrent PMU-session block already uses. That is roughly 33 us
        against 680 us, a twentyfold gap read by a nanosecond wall clock, so no
        timer resolution enters the measurement. It also costs less than the
        sleeping it replaces: the slow workers take about 14 ms rather than 60 ms.

        The assertion stands, since the ordering is the invariant worth holding, but
        its message now carries both medians so a failure on an unusual host reports
        numbers rather than a verdict.

        Verified on the failing environment, an Ubuntu 24.04 container with GNAT
        16.1.0 on aarch64: 30 of 30 runs pass where HEAD fails 9 of 20 in the same
        container, 20 of 20 under a two-CPU quota, and 10 of 10 with 24 competing
        spinners on that quota. scripts/test.sh passes three times from a fresh
        source export there and once on macOS. A calibration probe over 105 further
        trials across those CPU configurations held the ratio between 14x and 30x
        with no inversions and Relative_Change_Percent positive throughout.

      8. ae5b52d7
        Problem: A group snapshot cannot say whether its event loop is busy

        Flyology.Observability.Group_Snapshot carries thirty fields covering queue
        depths, wait categories, and cumulative counters, but none of them reports how
        much of an event loop's time was spent doing work. Pool imbalance is therefore
        invisible from outside the process: a group with a deep ready queue and a group
        that is idle produce the same evidence once their momentary queue depths match.
        Made_Progress detects a stalled loop but not a saturated one, and its comment
        already records why a per-dispatch clock read was rejected as the answer.

        Solution: Time the poller wait a loop takes when nothing is ready

        An event loop enters Wait_Batch only when its ready queue is empty, so the idle
        path is both the exact complement of the loop's working time and a path a busy
        loop never repeats. The scheduler stamps the wait before releasing the group
        lock and closes it after reacquiring, keeping the in-progress wait in the group
        so an observer adds it rather than charging a long block as busy time. Nothing
        is added to dispatch, context switch, or any other hot path.

        Group_Snapshot gains Uptime_Nanoseconds, Idle_Nanoseconds, and Idle_Waits, and
        the runtime snapshot ABI moves to version 6. Idle time is clamped to uptime and
        both come from one clock reading, so callers can always take the difference or
        the ratio. tests/native/process_lifecycle_probe.c pins that ABI and its layout,
        and moves with it.

        The cost is measured rather than asserted. runtime_callback_bench adds
        poller_idle_cycle for the instrumented path and monotonic_clock_read for the
        unit of work it adds; benchmarks/idle_wait_rate reports the rate a loop
        actually reaches, because the effect is far below what a differential timing
        run resolves on this host. On macOS/AArch64 a reading costs about 20 ns, a
        socket ping-pong reaches roughly 32,000 to 38,000 waits per second per loop,
        and a loop doing nothing else reaches roughly 120,000 to 160,000: under 0.2%
        and under 0.7% of a loop's time respectively.

        Checks run: ./scripts/test.sh (pass, including the new
        observability_utilization_smoke), ./scripts/docs.sh (pass, no new warnings),
        ./scripts/bench-runtime.sh.

      9. 6c4bfc3c
        Problem: The guide cannot tell a reader whether a group is busy

        Step 10 of the guide lists the readings that diagnose a group, but every one of
        them describes queue contents. A reader who wants to know whether an event loop
        is saturated has no entry to follow, and the utilization fields the runtime now
        publishes appear only in README.md and the generated API reference.

        Solution: Document loop utilization where the guide diagnoses a group

        A new subsection explains what the runtime measures, why the subtraction is
        always valid, and the two readings that look alike: a group whose tasks all
        wait resembles a group with nothing to do, and a task that never suspends keeps
        its loop out of the poller and reports as fully busy. A decision row places the
        measure next to the queue-depth readings it qualifies. The cost paragraph names
        the measured figures and the script that reproduces them, rather than asserting
        that the accounting is cheap.

        The worked example is compiled and run by tests/guide_utilization_example.adb.
        The first draft of that example did not compile, because Counter is a modular
        subtype and the subtraction needs a use type clause the guide had not shown. A
        test main is the only check that keeps a printed example honest about the
        visibility a reader must supply.

        Checks run: ./scripts/test.sh (pass, including the new
        guide_utilization_example), ./scripts/build-site.sh, and check-site.mjs over
        the built site as CI runs it.

      10. fb881640
        Problem: The utilization copy states a rule that does not hold

        The website/AGENTS.md technical review is required for any changed capability,
        limit, or timing claim, and running it on the new guide section found four
        faults.

        Two are wrong rather than unclear. The guide told a reader that `Counter` needs
        a `use type` clause because the subtype is modular; the clause is needed
        because the operators of a type declared in another package are not directly
        visible, so the stated rule teaches the wrong thing. The guide also said an
        event loop waits in its poller only when no task can run, but the loop polls
        with a zero timeout while work is ready, and the same section counts that
        polling as busy time.

        The remaining two narrow a claim that had become broader than the code.
        "Dispatching, polling with work ready, or running task code" reads as an
        exhaustive account of a loop's busy time and omits timer promotion, file
        submission, and cancellation processing. That wording appeared in the guide,
        README.md, and the Group_Snapshot field documentation, so all three change
        together. `Group_Snapshot` and `Snapshot` appeared only inside the code block
        and were linked nowhere in prose, which the API-link rule does not allow.

        Solution: Correct the two faults and narrow the two broad claims

        The editorial and controlled-language passes contributed three further changes:
        one repeated paragraph opening, "idle fraction" used before the section
        introduces it, and "reading" carrying both a clock read and a snapshot.

        Checks run: ./scripts/docs.sh (pass, no new warnings),
        ./scripts/build-site.sh with check-site.mjs over the built site,
        and observability_utilization_smoke, guide_utilization_example, and
        observability_smoke rebuilt and re-run.

      11. bca8ad7f
        Problem: Previewing the built site needs an ad-hoc server command

        scripts/build-site.sh writes the complete site to build/site, but nothing
        records how to serve it. Reading a guide page as it will be published means
        inventing a static-server invocation each time, and picking a port that does
        not collide with a development server already running.

        Solution: Record a launch configuration that serves the built site

        The entry serves build/site on port 8231. It reads the build output and does
        not produce it, so run scripts/build-site.sh first and again after editing
        anything under website/.

        Checks run: served build/site through the entry and loaded the guide page.

      12. 104d406f
        Problem: macOS L1 detection reports efficiency-core capacity

        The macOS body queries the flat hw.l1dcachesize sysctl. On a heterogeneous
        Apple silicon host that name reports the efficiency-core capacity, not the
        performance-core capacity: one 12P/4E host reports 65536 bytes for the flat
        name against 131072 for hw.perflevel0.l1dcachesize. Flyology_Cachelines.
        L1_Data_Cache_Size therefore reports half the performance-core L1d capacity,
        and L1_Data_Cache_Slots derives its slot count from that halved value.

        The reader also assumed every queried name stores a 64-bit value. It read
        each name into one 64-bit object and accepted a short reply, so a 32-bit
        value was correct only because Darwin is little-endian and the object was
        zero-initialized. The per-level names are 32-bit.

        Solution: Prefer the highest performance level and read the reported width

        macOS 12 and later describe a host whose cores are not identical as ordered
        performance levels, where hw.perflevel0 is the highest-performing level. The
        macOS body now queries hw.perflevel0.l1dcachesize and falls back to the flat
        name only on a host that publishes no performance level, such as macOS 11 and
        earlier or an Intel Mac. Querying hw.nperflevels first would add nothing: the
        per-level name exists exactly when the host publishes performance levels.
        Hardware_Cache_Line_Size is unchanged, because Darwin publishes no per-level
        line size and both Apple silicon core types use the same line.

        The public API keeps its Cache_Query_Result surface. Reporting per-level
        geometry is a separate design question, and it should not ride along in a
        detection correctness fix.

        The sysctl reader moves into a new private Flyology_Cachelines.Macos child,
        mirroring the existing Flyology_Cachelines.Linux split between mechanism and
        policy. It requests each name's stored width before reading the value and
        rejects any other width, so a 32-bit name, a 64-bit name, a string, and an
        absent name are all handled without depending on byte order. Failed and
        malformed queries still degrade to Unavailable rather than raising.

        The GNATdoc comments on L1_Data_Cache_Size and L1_Data_Cache_Slots, the crate
        README, and the website cachelines guide now state that a host whose cores are
        not identical reports one core type, and which one each platform reports. A new
        macOS detection test mirrors the Linux one: it exercises the sysctl reader
        directly and checks that the reported capacity is the highest performance level
        the host publishes.

        Checks run: ./flyology_cachelines/scripts/test.sh (the native test now reports
        131072 bytes of L1 data cache on a 12P/4E host, and the new macOS detection
        test passes) and ./flyology_cachelines/scripts/docs.sh (zero GNATdoc warnings).

      13. d3af8647
        Problem: The Linux detection test requires an optional mechanism

        Flyology_Cachelines.Linux_Testing asserts that both Detect_From_Sysconf and
        Detect_From_Sysfs report a value. Only their composition is guaranteed:
        glibc answers _SC_LEVEL1_DCACHE_SIZE and _SC_LEVEL1_DCACHE_LINESIZE from
        CPUID on x86-64, but reports zero on aarch64, where sysfs is the only
        mechanism. Detect already treats sysconf as optional and falls back to
        sysfs, so the test is stricter than the code it covers.

        The test therefore fails on aarch64 Linux with "sysconf cache detection
        failed". CI runs ubuntu-latest on x86-64, where sysconf answers, so the
        failure is invisible there. It reproduces on aarch64 Linux, which AGENTS.md
        tells contributors to prefer on Apple silicon because it is native and
        faster.

        Solution: Require the composition and check each available result

        Run now requires that at least one mechanism reports a value, and checks
        consistency only for a mechanism that reported one. That is what the
        production detector promises: it composes sysconf and sysfs, and returns
        Unavailable only when neither answers.

        Checks run: the crate suite on aarch64 Linux in a container, where the
        detection test now passes, and on macOS, where it is not built.

      14. 04658ed7
        Problem: Linux cache detection describes only CPU 0

        Flyology_Cachelines.Linux reads one L1 data-cache geometry: sysconf answers
        for the calling CPU, and the sysfs fallback reads cpu0. A host whose cores
        are not identical has more than one geometry, and neither mechanism says
        which core the reported one belongs to, or that others exist.

        macOS already publishes ordered performance levels, so the macOS body can
        prefer the highest-performing one. Linux publishes per-CPU descriptions and
        no single ordering, so the equivalent information has to be derived before
        any public per-core-type query can work on both platforms.

        Solution: Group CPUs into core classes and record what ordered them

        Detect_Core_Classes enumerates the CPUs the host lists as present, reads
        each one's L1 data-cache geometry and capacity, groups CPUs reporting
        identical values into a class, and counts each class.

        Classes are grouped on capacity and geometry together. Grouping on geometry
        alone merges two core types that happen to share an L1 data-cache size,
        which real designs do.

        Ordering uses whichever key separates the classes, and Core_Classes reports
        which one did, so a caller can tell an authoritative order from an inferred
        one:

        - Host_Reported: the kernel's per-CPU capacity values separated them.
        Capacity is the scheduler's own measure of relative CPU performance and
        accounts for microarchitecture and clock. Architectures selecting the
        generic topology code publish it under cpuN/cpu_capacity.
        - Inferred: no capacity separated them, so they are ordered by descending
        L1 data-cache capacity. That holds on current hybrid parts and carries
        no meaning on a host whose classes differ some other way. x86-64 does
        not publish capacity, so its hybrid parts land here.
        - Unordered: fewer than two classes, or nothing separated them.

        Cores and CPUs are counted separately. SMT siblings share one L1 data cache,
        so the cache's sharing list identifies which CPU represents a physical core.
        Counting logical CPUs as cores overstates a 24-core host with two threads
        per core by a factor of two.

        Detection fails closed. A missing or malformed CPU list leaves only CPU 0 to
        enumerate, enumeration is bounded, a CPU whose description cannot be read is
        skipped, and a host reporting more classes than the table holds reports none
        rather than a table that silently omits a class.

        Detect_Core_Classes takes the CPU root as a parameter defaulted to the real
        sysfs path. Grouping, ordering, and the SMT distinction cannot be reached on
        a uniform test host, so the detection test drives them with committed
        fixture trees: two classes separated only by capacity, two classes separated
        only by geometry with the smaller listed first, SMT pairs sharing one cache,
        and a CPU list with a gap.

        Nothing calls Detect_Core_Classes outside the test yet. The public
        per-core-type query, and the elaboration cost of walking every CPU, belong
        to the change that adds that query.

        Checks run: the crate suite on aarch64 Linux in a container and on macOS.
        Detection was also replayed against captured CPU descriptions from a 48-CPU
        x86-64 host with two threads per core, which reports 24 cores against 48
        CPUs and no capacity, and from an 80-CPU aarch64 host, which reports 80
        cores against 80 CPUs and a published capacity.

      15. ba8438da
        Problem: Cache queries cannot name a core class

        Flyology_Cachelines reports one L1 data-cache capacity. A host that combines
        core types has one per type, so a single value silently describes whichever
        type the platform body happened to pick and gives a caller no way to ask
        about the others, or to learn that others exist.

        The two platforms also disagreed. macOS reported the highest performance
        level, while Linux reported whichever cache its own mechanism described:
        sysconf for the calling CPU, sysfs for cpu0. The same call therefore meant
        different things on the two platforms.

        Solution: Make the core class an explicit parameter of every cache query

        Core_Class names one class of cores that report a single cache geometry.
        Core_Class_Count reports how many the host distinguishes, Core_Class_Cores
        and Core_Class_CPUs describe each one, and L1_Data_Cache_Size and
        L1_Data_Cache_Slots take the class they describe. The parameter defaults to
        Fastest_Core_Class, so existing calls keep compiling and now mean the same
        thing on both platforms: the class the host ranks highest.

        Core_Class_Ordering reports what produced that rank, because it is a host
        fact on some platforms and the crate's inference on others. macOS performance
        levels and the Linux per-CPU capacity values are Host_Reported. A host
        publishing no rank is Inferred, ordered by descending L1 data-cache capacity.
        Fewer than two classes is Unordered.

        Cores and CPUs are reported separately. Sibling CPUs under simultaneous
        multithreading share one core's L1 data cache, so a 24-core host with two
        threads per core reports 24 cores and 48 CPUs in one class.

        Hardware_Cache_Line_Size takes no class. macOS publishes no per-class line
        size, and the core types of current heterogeneous parts share one line size,
        so a per-class query would have one answer to give.

        The host is now inspected on first use rather than during elaboration.
        Describing every class means reading one description per CPU on Linux, which
        measures 14 ms for 48 CPUs and 24 ms for 80. A program that links this crate
        and never asks about the host should not pay that at startup. The inspection
        is idempotent, so a race on the first query can duplicate work but cannot
        produce a value neither caller computed; the ready flag is atomic and is set
        after the result is stored.

        Flyology_Cachelines.Platform now answers one Detect call describing the whole
        host, and the root package body owns the single memoization. The two Linux
        bodies share one translation and differ only in what they report when sysfs
        describes nothing: the x86-64 body can still read the calling CPU through
        CPUID. Flyology_Cachelines.Linux drops its own class and ordering types in
        favour of the public ones, so the crate has one Core_Class.

        The website cachelines guide is corrected alongside the API. Adding the Class
        parameter changed the generated GNATdoc anchors for L1_Data_Cache_Size and
        L1_Data_Cache_Slots, so the guide's links to them became dangling fragments;
        both now point at the regenerated anchors. The guide also claimed detection
        happens during package elaboration, which is no longer true. The new entities
        are linked to their generated entries on first mention.

        Checks run: the crate suite on macOS, where a 12P/4E host reports two
        host-ordered classes of 131072 and 65536 bytes across 12 and 4 cores; on
        aarch64 Linux in a container; and on an x86-64 Linux host with 24 cores and
        two threads per core, which exercises the CPUID body and reports 49152 bytes
        across 24 cores and 48 CPUs. GNATdoc builds with no warnings.

      16. 9782c81b
        Problem: The shared L2 cache is not reported

        Flyology_Cachelines reports L1 but not L2, so a caller sizing a working set
        against the level it will actually spill into has nothing to read.

        The flat sysctl this crate would naturally have used is wrong in the same way
        hw.l1dcachesize was, and by a larger factor. On a 12P/4E Apple silicon host
        hw.l2cachesize reports 4194304, the efficiency cluster's cache, against the
        performance cluster's 16777216. Adding L2 before core classes existed would
        have reproduced the original defect at four times the size instead of two.

        Reporting a capacity alone would also mislead. L2 is rarely private: that same
        host shares 16 MiB across six performance cores and 4 MiB across four
        efficiency cores, so neither figure is a per-core budget.

        Solution: Report L2 capacity and how many cores share it, per class

        L2_Cache_Size and L2_Sharing_Cores take the same core class as the L1
        queries. A sharing count of one means the cache is private to a core; a
        larger count means the reported capacity is divided among that many cores.
        The GNATdoc on each function points at the other, because reading either
        alone invites the per-core mistake.

        macOS reads hw.perflevelN.l2cachesize and hw.perflevelN.cpusperl2. Linux
        reads the level 2 entry of each CPU's cache description, counting the CPUs
        its shared_cpu_list names. Both counts arrive as logical CPUs and become core
        counts through the class's own threads-per-core ratio, so a host with two
        threads per core does not report twice the cores sharing a cache.

        Parsing a CPU list needs more than its leading index, so the Linux body gains
        List_Count, which sums the single indexes and inclusive ranges a list names.
        Describing L2 costs no extra file reads: the level 2 entry is found in the
        same pass over the cache indexes that already locates the level 1 data entry.

        The website cachelines guide gains the same pairing, with both names linked
        to their generated entries.

        Checks run: the crate suite on all three supported targets. A 12P/4E macOS
        host reports 16777216 bytes across 6 cores for its performance class and
        4194304 across 4 for its efficiency class, and the macOS test asserts that
        these come from the performance level rather than the flat name. An aarch64
        Linux host reports 16777216 across 6 cores. An x86-64 Linux host with 24
        cores and two threads per core reports 2097152 across 1 core, where sysfs
        gives 2048K shared by CPUs "0,24"; that run also compiles the CPUID body,
        which builds nowhere else. Fixtures cover a per-class shared L2, an L2 shared
        across SMT siblings, and a private L2. GNATdoc builds with no warnings.

    5. 9782c81b updated to 7be049fcindex 6e2db0ef

      1 source commit

      1. 7be049fc
        Problem: A stalled package mirror hangs CI instead of failing it

        The two OpenSSL install steps in the test job carried no bound, so a mirror
        that stops answering leaves apt waiting rather than returning an error. On
        2026-08-19 run 32297071503, job 96211136305 sat on "Install OpenSSL 3 on
        Linux" for 32 minutes and had to be cancelled by hand; it was the only check
        blocking PR #49. Its log shows apt-get update fetching noble-security
        InRelease at 20:13:04 and producing no further output until cancellation. The
        macOS half of the same job passed, so nothing was wrong with the tests.

        Left alone the job would have run to GitHub's six-hour default. Nothing else
        in either workflow was bounded either: the checkout, the Alire install, the
        index configuration, the Java and TLA+ downloads, and the GNATdoc install all
        reach the network under the same default, and no job in this repository
        declared a timeout at all, unlike the sibling repositories.

        Solution: Bound every job and every step that reaches the network

        Each job now declares a timeout-minutes, and so does each step that fetches
        something. The bounds are generous multiples of what healthy runs measure
        over the last 60 successful runs of each workflow, so they can only fire on a
        stall. Jobs: test observes at most 17 minutes on macOS and 11 on Linux and is
        bounded at 60; proof observes 6 minutes and TLA+ 7, both bounded at 30; the
        pages build observes 69 seconds and is bounded at 20, its deploy 10 seconds
        and bounded at 15. Steps: everything network-touching is bounded at 10
        minutes against observed maxima of 1 to 6 seconds, except the Alire install,
        which downloads the toolchain, observes 100 seconds, and is bounded at 15.

        A step timeout alone would only have converted the 32-minute hang into a
        10-minute one, because the stall is inside a single apt-get update that never
        returns. That command is now capped per attempt with timeout(1) and retried
        twice with 15 and 30 second backoff, so one unresponsive mirror costs a
        retry rather than the job. The install that follows is capped as well but not
        retried: a package that cannot be resolved should fail on the first try. The
        worst case is three 120-second attempts plus a 10-second kill grace, 45
        seconds of backoff, and a 190-second install, which is 10m25s and lands
        inside the 12-minute step bound, so the annotation naming the transient
        mirror is what the log ends on rather than a bare cancellation.

        GNU timeout is used directly rather than scripts/run-with-timeout.sh. That
        helper exists for portability to macOS, and this step is Linux-only.

        The TLA+ download gains --connect-timeout 30 and --max-time 120 alongside its
        existing --retry 3, because curl retries a failed transfer but not a stalled
        one, and --max-time resets per attempt. Four bounded attempts stay inside the
        step's 10 minutes.

        Build, test, proof, and model-checking steps keep no step bound. Their
        duration is workload-dependent, a bound sized for them would be a performance
        budget rather than a stall detector, and the job timeout already covers them.
        Nothing about what is installed, or how anything is built or tested, changes.

        Checks run: both workflows parse. The retry script was extracted from the
        committed YAML and driven under bash -e against stub apt-get invocations for
        five outcomes: first-try success runs one update and one install; two
        failures then success runs three updates and installs; three failures exit 1
        with the annotation and never install; an install failure propagates its exit
        status without retrying; and exit 124, which is what timeout(1) reports when
        it kills a stalled command, is treated as retryable. The real commands were
        then run in an ubuntu:24.04 container on coreutils 9.4, the runner's version:
        the bounded update succeeds, interrupting one mid-flight reports 124, a
        retry after that kill still succeeds rather than inheriting a poisoned apt
        state, and the bounded install still yields OpenSSL 3.0.13 through pkg-config.

        The convention is recorded in AGENTS.md so it holds for new steps, and it
        matches the job-level timeouts already used in flyology-http and
        gnat-patches, whose install steps want the same treatment.

        Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

    6. 7be049fc updated to a53da35dindex b5569962

      1 source commit

      1. a53da35d
        Problem: The allocators dependency accepts any version

        The allocator crate is developed alongside the runtime in this repository and
        released on the same development line, but the dependency on it is declared as
        "*". Nothing stops a dependent from resolving an allocator release built for a
        different line, and the index has been carrying a tighter constraint by hand to
        compensate.

        Solution: Constrain allocators to its development line

        Declare the line the allocator crate actually publishes, so the constraint
        travels with the manifest instead of being reapplied wherever it is indexed.

        Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

    Dependency changes

    • Added flyology_allocators ~0.1.0-dev
    Compare source revisions
    Development update

    flyology_allocators 0.1.0-dev

    4 updates: 9a24bf68 through a53da35d

    Caller-owned memory allocation algorithms for Ada

    Manifest fields
    origin
    Show all 4 updates
    1. 9a24bf68 updated to 60de2c69index 8a8e9de5

      1 source commit

      1. 60de2c69
        Problem: A development pin ships in the published manifest

        flyology.gpr imports flyology_allocators.gpr, and the manifest both declares
        flyology_allocators as a dependency and pins it to the in-repo directory.
        Alire honours pins only in a root crate's manifest, so a consumer resolving
        flyology from the index never receives that dependency. Its solution omits
        flyology_allocators entirely and gprbuild then fails with "imported project
        file flyology_allocators.gpr not found". A crate whose only dependency is
        flyology = "~0.1.1-dev" reproduces it in two lines.

        Nothing in this repository reports the fault, because the pin satisfies the
        dependency for every build performed here. The pin also hid two further
        assumptions that only the in-repo directory could satisfy.

        Solution: Resolve the allocators dependency from the index

        Drop the pin so the declared dependency resolves the same way for this crate
        and for its consumers. The published flyology_allocators 0.1.0-dev is built
        from this repository at the same commit and the same subdirectory, so the
        source reached is identical; only the path by which it is reached changes.

        Configure the organization index in this repository's own workflows. They
        carried the community index alone, because the pin meant no job here ever
        resolved flyology_allocators from an index, and it is published only in the
        organization index. Without that step alr reports an incomplete solution
        naming flyology_allocators as missing.

        Name the excluded documentation project through the imported project rather
        than through a repository path. Documentation.Excluded_Project_Files listed
        flyology_allocators/flyology_allocators.gpr, which resolved only while the
        crate sat in this working tree; as a dependency its project lives in the
        Alire build tree under a content hash. Flyology_Allocators'Project_Dir asks
        the imported project where it is, so the exclusion holds wherever the
        dependency is deployed and the allocator packages stay out of this crate's
        generated API, where they would otherwise be documented twice.

        Record the rule that produced the fault in the agent guide: no committed
        pins in a crate manifest, alr pin in the consuming workspace for unpublished
        work, and a declared dependency must resolve from the index. Name the
        gprbuild error there too, since that is where the fault appears and it names
        a project file rather than a crate.

    2. 60de2c69 updated to 9782c81bindex 75a836be

      16 source commits

      1. aeb10612
        Problem: The site does not list Flyology RDF

        The hero project map, the standalone catalogue, the library ledger, and
        llms.txt each name every component. Flyology RDF publishes a website, a
        guide, and three generated API references at rdf.flyology.org, but the name
        appears nowhere in this repository. A reader who arrives at the site and
        looks for what Flyology offers does not learn that the project exists.

        Solution: Add the project to the hero map, catalogue, ledger, and llms.txt

        flyology_rdf depends on flyology_iri only. It needs no runtime preparation
        and starts no tasks, so it belongs with the standalone libraries. Every list
        keeps its alphabetical order, so the entry sits between Flyology NUMA and
        Flyology SIMD and the ledger indices shift from S07..S08 to S08..S09.

        The ledger and llms.txt entries carry all three generated references, as the
        Flyology Postgres entries already do, because the project site treats the
        Notation3 and SPARQL APIs as first-class navigation.

        The llms.txt project-structure summary also omitted Flyology Allocators and
        Flyology NUMA, which the same file already listed further down. Both names
        join the summary here.

        Verified with the website-kit site checker, whose output is unchanged from
        the pre-change baseline, and by rendering the pages: the hero, catalogue,
        and ledger all name the project. The six linked URLs return 200.

      2. 2188ee0d
        Problem: The project map announces its framing and then hides the components

        The figure caption claimed "One project, two adoption paths" above two cards
        that already carry the same fact in their labels, so the caption restated
        what the diagram shows. The two card subtitles were not parallel either:
        "Core component" named a role while "No runtime dependency" named a
        dependency, so neither pair member helped a reader compare the paths.

        The component names below them were plain list items. A reader who found the
        name that matched the problem had no way to reach the component from the
        diagram and had to scroll to the catalogue to find the same name again.

        Solution: Drop the caption, make the subtitles parallel, and link the names

        The subtitles now read "Prepare the runtime" and "Add a crate", which state
        the two adoption paths as the actions they are. The figure keeps an
        accessible name through aria-label, and the figcaption rule leaves the
        stylesheet with the element it styled.

        Each component name becomes a link to its best available destination, which
        is the destination the catalogue below already uses: the project site where
        one exists, then the guide, then the generated API, then the source tree.
        The pill moves from the list item to the anchor so the whole badge is the
        hit target. Links open in a new tab and carry no underline, as requested, so
        hover brightens the border and adds a faint fill instead. Each list states
        the new-tab behavior once in its aria-label rather than repeating it in
        twelve hidden spans.

        Verified by rendering the page: every badge computes text-decoration-line
        none and cursor pointer, and the hovered badge is distinguishable from its
        neighbors. The site checker reports one new line against the baseline,
        api/flyology_debug/ from the new Debug badge, which resolves once
        scripts/docs.sh generates the GNATdoc output that this partial build omits.

      3. 5dfd5d36
        Problem: Nothing coordinates tools that need exclusive CPU capacity

        Two measurement runs that share a machine produce two wrong answers, and
        neither run can tell that it happened. The problem is not confined to
        benchmarks: a load generator, a soak test, or a profiler makes the machine
        loud, and a benchmark needs it quiet. Both want the same thing from opposite
        directions, and nothing lets them find each other.

        Worse, two runs that each suspend collection when they detect interference
        are symmetric controllers observing each other. Each pauses because the other
        is loading the machine, both then observe quiet, both resume together, and
        both immediately pause again.

        Solution: Specify a host CPU lock convention and implement it

        The convention is named for the resource rather than for benchmarking, so
        that the tools which create load take the same claim as the tools which need
        its absence. Conflict detection is flock and nothing else: liveness is the
        lock itself, so a holder that dies releases with no cleanup path, no stale
        registry entries, and no pid-reuse hazard.

        A machine-wide claim takes LOCK_EX on the claim file; a claim on individual
        CPUs takes LOCK_SH there and LOCK_EX on one file per CPU. Disjoint core-scoped
        claims therefore proceed concurrently while a machine-wide claim excludes them
        all, with no registry and no arbiter. Per-CPU claims are acquired in ascending
        order, because a total order is what stops two callers with overlapping sets
        from deadlocking on each other's partial claims.

        The path is a single deterministic default rather than a writability-probing
        fallback chain. A chain reintroduces the failure it was meant to prevent:
        /run/lock is 1777 on Debian and root-owned 0755 on Red Hat derivatives, so a
        root process and an unprivileged process on one machine would probe
        differently, land on different files, and each conclude it holds the machine.
        $TMPDIR is avoided for the same reason, being per-user on macOS.

        File content is diagnostic and is never consulted to decide conflicts. It is
        still specified and parseable, one key=value pair per line, because a reader
        must be able to name the holder; cwd is included because tool and pid alone do
        not distinguish one checkout or CI workspace from another. Readers open the
        file without locking, since a shared lock would block behind the very holder
        they are trying to identify, and must tolerate content that is empty, stale,
        or half-written.

        A claim is not proof of exclusivity, and the implementation does not present
        it as one. systemd PrivateTmp= bind-mounts a per-service directory over /tmp,
        so two services share every CPU and cannot see each other's claim files; that
        case is detected from /proc/self/mountinfo and reported as namespace-scoped.
        Separate containers are not detectable from inside and need an explicit shared
        path. A path can be proven private but never proven machine-wide.

        Only the C macros live in the native unit. GNAT's C_Variadic_2 convention
        calls open() correctly even on Darwin/AArch64, where variadic arguments are
        passed differently from fixed ones, so the protocol, the file grammar, and the
        /proc reader are all Ada. The convention compiles on every GNAT this crate
        supports, checked against 13.2.2 through 16.1.0 against an alire.toml floor of
        13, so no compatibility shim is carried.

        Verified by building the crate, and by taking claims on disk: the file matches
        the published grammar, parses with awk -F=, is created 0666, and per-CPU files
        are named beside the machine file.

      4. 13b71a5b
        Problem: The CPU gate only proves the host was quiet before warmup

        CPU_Quiescence samples host counters once, before clock characterization, and
        then never looks again. A machine that goes busy halfway through collection
        produces a result that reads as clean, and nothing in the measurement, the
        console card, or the machine-readable output says otherwise. The gate's own
        documentation admits it "cannot prevent new load from arriving after
        collection begins", and until now that was the end of the story.

        The obvious repair is not available either. Host utilization cannot simply be
        compared against a limit during collection the way the preflight does it,
        because by then the benchmark thread saturates a core and every sample would
        trip the limit.

        Solution: Watch for foreign load during collection and say what was found

        Foreign load is host busy time minus this process's own CPU time, so load the
        benchmark itself creates is correctly not foreign. The estimate scales the
        host busy ratio by wall time rather than converting ticks, so the platform
        tick length never enters the arithmetic. Cross-checked against top on a loaded
        machine, the two agree to within 0.1 percent.

        Three responses form a ladder. Observe records and keeps everything. Retake
        discards the contaminated window and collects it again. Pause waits for the
        host to settle, re-warms, and then collects it again. The re-warm is not
        politeness: a resumed run has cold caches, predictors, and frequency state, so
        without it the first sample after a pause is the outlier the pause existed to
        avoid.

        Nothing adjusts a reported statistic. A skew factor derived from observed load
        would be invented data, because the cost of interference depends on whether
        the contention is an SMT sibling, a shared cache, memory bandwidth, or another
        socket, and the same foreign share can mean no slowdown or a large one. Runs
        are annotated or repaired, never corrected.

        Observation happens between timed samples over windows of whole collection
        units, where a unit is one sample, one comparison pair, or one balanced
        multi-way round. A response therefore never splits the two halves of a pair
        and never lands mid-round, where it would spread interference unevenly across
        the cases a round exists to compare fairly. Windows carry a margin over the
        configured minimum: sized to only just reach it, ordinary batch jitter drops
        them below it and they silently degrade to observation. Host counters are
        tick-based, so a window that still falls short is recorded but never acted on.

        Discarding a window rolls back what the window changed. Per-sample values are
        written by index and survive a retake intact, but the position tally of a
        comparison pair and the process-telemetry summaries are running sums, so a
        discarded pass gives them back. Without that, a run with eighteen retained
        samples and twenty-four retakes would report elapsed time and an average CPU
        share covering forty-two samples, most of which were thrown away.

        Budgets degrade rather than abort. An exhausted retake or pause budget
        continues under Observe and reports it, and paused time is excluded from
        Maximum_Sampling_Time because waiting for the host is not collection.

        Placement is optional and sharpens attribution: with a strict binding every
        other CPU's busy time is foreign outright, and the placed CPU's share is its
        busy time minus the placed thread's own. SMT siblings join the watched set,
        because a process saturating the sibling of the placed CPU slows the
        measurement while leaving the placed CPU's own share clean, which makes
        sibling-blind core-scoped observation worse than host-wide observation rather
        than better. Placement is Linux-only in practice; Apple Silicon implements no
        thread affinity and rejects every request, so the Host_Control documentation
        no longer describes Darwin placement as merely advisory.

        Placement binds only the calling thread, so another thread of this process can
        occupy a watched CPU, where its time is indistinguishable from foreign load.
        Each window therefore reads process CPU as well as thread CPU, and their
        difference bounds how much of the watched capacity those threads could account
        for. Once that bound exceeds the configured foreign limit, the core-scoped
        answer can no longer address the question the limit asks: the run drops to
        host-wide observation, which is well defined for a multi-threaded process, and
        reports Attribution_Diluted. Otherwise a scheduler benchmark run under
        placement would spend its retake budget discarding samples over load it
        created itself. The window that reveals the dilution is discarded rather than
        recorded, because its value was computed under the attribution being
        abandoned.

        The direction of that fallback is deliberate. Core-scoped attribution
        subtracts only the placed thread, which over-reports interference when other
        threads share the watched CPUs; subtracting the whole process instead would
        deduct time our threads spent on CPUs outside the watched set, under-report
        foreign load, and let contaminated data pass as clean. Over-reporting shows up
        in the retake and contamination counts; under-reporting shows up nowhere.

        The host CPU claim is taken before the preflight gate, since waiting for a
        quiet host and then blocking on the claim leaves the quiet verdict stale.

        Everything observed reaches the console card, the CSV schema, and the JSON
        object. That visibility is the point: a run that had to repair itself must say
        so, or a heavily repaired result reads as a quieter machine than the one it
        ran on.

        Verified with ./scripts/test.sh on Darwin/aarch64 and in an Ubuntu 24.04
        container on Linux/aarch64, and under qemu-system-aarch64 across four CPU
        topologies. Core-scoped attribution asserts that it closed an observation
        window, so the thread-CPU probe it depends on cannot fail silently. Two
        assertions were checked against builds that defeat them: one with sibling
        collection disabled fails the sibling assertion under cores=2,threads=2 and
        passes without SMT, and one with the dilution check disabled fails the
        fallback assertion while a task of the test's own process burns CPU. Retake
        and pause are driven by a spawned process, because load raised inside this
        process is its own CPU time and is subtracted by design.

      5. 845bdaca
        Problem: The new guide section ignores the site's writing rules

        website/AGENTS.md governs hand-written pages under guide/**. The interference
        section met none of its API-link requirements and several of its style rules.

        Every public entity it introduced went unlinked: Interference, Placement,
        Host_Lock, the three Interference_Response literals, Maximum_Retakes, Window,
        Rewarm_Time, Maximum_Foreign_CPU_Percent, Include_Siblings, Require_Strict,
        Attribution_Diluted, and Environment. The same page already links
        CPU_Quiescence, Stable_Time, and Timeout, so the new section also read
        inconsistently against its own neighbours.

        Solution: Link the API entities and apply the three prescribed reviews

        The three reviews ran in sequence and are labelled here, since separate review
        agents were unavailable.

        Technical. "Foreign load is host busy time minus this process's own CPU time"
        held only without placement, because core-scoped attribution subtracts the
        placed thread rather than the whole process; the sentence now says so, and the
        placement paragraph states which CPUs the harness measures. "The re-warm is
        required" overstated a configurable field, so the text names Rewarm_Time and
        says what a zero value leaves behind. "When the difference exceeds the
        configured limit" named neither the limit nor the compared quantity, which
        also left Maximum_Foreign_CPU_Percent unlinked. Two harnesses that both pause
        do not deadlock as claimed; they alternate between pausing and resuming.

        Editorial. "This matters most" and "Without it" both referred back to
        something unnamed. Both now name their subject.

        Controlled language. "Sharpens attribution" was figurative and is now
        "narrows attribution to the placed CPU and its SMT siblings". "A run that
        repaired itself reports that fact" personified the run; the report is the
        actor, and it states counts.

        Verified with ./scripts/build-site.sh and the site checker, which passes 144
        HTML files. All fourteen API links resolve to an existing anchor in the
        generated GNATdoc output, and each target matches the entry the API search
        index gives for that entity. No sentence in the section exceeds the 25-word
        review signal.

      6. edf788ef
        Problem: The guide does not say the host controls are opt-in

        The interference section described three capabilities without saying that a
        run acquires none of them unless it asks. BENCH 07 states that contract for
        the preflight gate, and the page marks the default value of a choice where one
        exists, as it does for Equal_Time and Balanced_Rounds. The new section did
        neither, so a reader could not tell that enabling the watch alone changes
        nothing about the collected data.

        The claim file was also absent. The page named three environment variables but
        not the one path that other tools must agree on, leaving the coordination
        surface a click away in the convention document.

        Solution: State the defaults, the claim path, and the budget interaction

        Observe is now marked as the default response, in the form the page already
        uses. The closing paragraph mirrors BENCH 07: the watch, placement, and the
        host claim are disabled by default, so an existing run acquires no new wait or
        failure condition. The opening sentence calls the watch optional where the
        reader first meets it.

        The claim paragraph names /tmp/host-cpu.lock, the Path field that overrides it
        for one run, and the HOST_CPU_LOCK_PATH variable that overrides it for every
        tool following the convention. An earlier draft named only the variable, which
        implied it was the sole override; the technical review caught that against
        Resolved_Path and Try_Acquire.

        The Window row gains the limit that qualifies it. A window covers whole units,
        so a window spanning many short samples can exceed Maximum_Retakes on its
        first discard. Collection then continues under Observe and reports the
        exhausted budget, which otherwise looks like the response never ran.

        Numeric field defaults are deliberately not repeated here. No other section of
        the page tabulates them, every field now links to its generated entry, and a
        duplicated value is one that can go stale.

        Verified with ./scripts/build-site.sh and the site checker, which passes 144
        HTML files. All fifteen API links resolve to an existing anchor, and each
        target matches the entry the API search index gives for that entity, including
        the ambiguous Path simple name, which resolves to Host_Lock_Policy.Path. No
        sentence in the section exceeds the 25-word review signal, and no entity is
        linked twice.

      7. 4fbe5020
        Problem: The recording smoke test separates its workloads with a delay

        recording_smoke drives two benchmarks from four tasks and asserts that the
        slow benchmark's recorded median wall time exceeds the fast one's. The
        separation comes from delay 0.000_2 against delay 0.000_8. A relative delay
        is rounded up to the host timer tick, and on a Linux kernel with a coarse
        tick both requests wake at the same boundary near 3 ms. A four-task probe
        with no recorder involved shows the first iteration of each task honoring
        the request and every later one landing on the same plateau:

        0.0002 s: 323 3710 2829 2972 3069 2947 ... (us)
        0.0008 s: 1167 3307 2482 3625 2793 3045 ... (us)

        The two recorded medians then arrive at 2.98 ms and 2.99 ms, ordered by
        scheduling noise alone. On Ubuntu 24.04 with GNAT 16.1.0 on aarch64 the
        assertion fails about half the time: 9 of 20 runs on a clean checkout. macOS
        resolves the two delays apart, which is why the test has held there. The
        independent comparison checked two assertions below rests on the same
        separation and fails with it.

        Solution: Separate the distributions by work the workers perform

        Each worker spins a volatile rotate-and-xor accumulator, 20_000 rounds for
        the fast benchmark and twenty times that for the slow one, the idiom the
        file's concurrent PMU-session block already uses. That is roughly 33 us
        against 680 us, a twentyfold gap read by a nanosecond wall clock, so no
        timer resolution enters the measurement. It also costs less than the
        sleeping it replaces: the slow workers take about 14 ms rather than 60 ms.

        The assertion stands, since the ordering is the invariant worth holding, but
        its message now carries both medians so a failure on an unusual host reports
        numbers rather than a verdict.

        Verified on the failing environment, an Ubuntu 24.04 container with GNAT
        16.1.0 on aarch64: 30 of 30 runs pass where HEAD fails 9 of 20 in the same
        container, 20 of 20 under a two-CPU quota, and 10 of 10 with 24 competing
        spinners on that quota. scripts/test.sh passes three times from a fresh
        source export there and once on macOS. A calibration probe over 105 further
        trials across those CPU configurations held the ratio between 14x and 30x
        with no inversions and Relative_Change_Percent positive throughout.

      8. ae5b52d7
        Problem: A group snapshot cannot say whether its event loop is busy

        Flyology.Observability.Group_Snapshot carries thirty fields covering queue
        depths, wait categories, and cumulative counters, but none of them reports how
        much of an event loop's time was spent doing work. Pool imbalance is therefore
        invisible from outside the process: a group with a deep ready queue and a group
        that is idle produce the same evidence once their momentary queue depths match.
        Made_Progress detects a stalled loop but not a saturated one, and its comment
        already records why a per-dispatch clock read was rejected as the answer.

        Solution: Time the poller wait a loop takes when nothing is ready

        An event loop enters Wait_Batch only when its ready queue is empty, so the idle
        path is both the exact complement of the loop's working time and a path a busy
        loop never repeats. The scheduler stamps the wait before releasing the group
        lock and closes it after reacquiring, keeping the in-progress wait in the group
        so an observer adds it rather than charging a long block as busy time. Nothing
        is added to dispatch, context switch, or any other hot path.

        Group_Snapshot gains Uptime_Nanoseconds, Idle_Nanoseconds, and Idle_Waits, and
        the runtime snapshot ABI moves to version 6. Idle time is clamped to uptime and
        both come from one clock reading, so callers can always take the difference or
        the ratio. tests/native/process_lifecycle_probe.c pins that ABI and its layout,
        and moves with it.

        The cost is measured rather than asserted. runtime_callback_bench adds
        poller_idle_cycle for the instrumented path and monotonic_clock_read for the
        unit of work it adds; benchmarks/idle_wait_rate reports the rate a loop
        actually reaches, because the effect is far below what a differential timing
        run resolves on this host. On macOS/AArch64 a reading costs about 20 ns, a
        socket ping-pong reaches roughly 32,000 to 38,000 waits per second per loop,
        and a loop doing nothing else reaches roughly 120,000 to 160,000: under 0.2%
        and under 0.7% of a loop's time respectively.

        Checks run: ./scripts/test.sh (pass, including the new
        observability_utilization_smoke), ./scripts/docs.sh (pass, no new warnings),
        ./scripts/bench-runtime.sh.

      9. 6c4bfc3c
        Problem: The guide cannot tell a reader whether a group is busy

        Step 10 of the guide lists the readings that diagnose a group, but every one of
        them describes queue contents. A reader who wants to know whether an event loop
        is saturated has no entry to follow, and the utilization fields the runtime now
        publishes appear only in README.md and the generated API reference.

        Solution: Document loop utilization where the guide diagnoses a group

        A new subsection explains what the runtime measures, why the subtraction is
        always valid, and the two readings that look alike: a group whose tasks all
        wait resembles a group with nothing to do, and a task that never suspends keeps
        its loop out of the poller and reports as fully busy. A decision row places the
        measure next to the queue-depth readings it qualifies. The cost paragraph names
        the measured figures and the script that reproduces them, rather than asserting
        that the accounting is cheap.

        The worked example is compiled and run by tests/guide_utilization_example.adb.
        The first draft of that example did not compile, because Counter is a modular
        subtype and the subtraction needs a use type clause the guide had not shown. A
        test main is the only check that keeps a printed example honest about the
        visibility a reader must supply.

        Checks run: ./scripts/test.sh (pass, including the new
        guide_utilization_example), ./scripts/build-site.sh, and check-site.mjs over
        the built site as CI runs it.

      10. fb881640
        Problem: The utilization copy states a rule that does not hold

        The website/AGENTS.md technical review is required for any changed capability,
        limit, or timing claim, and running it on the new guide section found four
        faults.

        Two are wrong rather than unclear. The guide told a reader that `Counter` needs
        a `use type` clause because the subtype is modular; the clause is needed
        because the operators of a type declared in another package are not directly
        visible, so the stated rule teaches the wrong thing. The guide also said an
        event loop waits in its poller only when no task can run, but the loop polls
        with a zero timeout while work is ready, and the same section counts that
        polling as busy time.

        The remaining two narrow a claim that had become broader than the code.
        "Dispatching, polling with work ready, or running task code" reads as an
        exhaustive account of a loop's busy time and omits timer promotion, file
        submission, and cancellation processing. That wording appeared in the guide,
        README.md, and the Group_Snapshot field documentation, so all three change
        together. `Group_Snapshot` and `Snapshot` appeared only inside the code block
        and were linked nowhere in prose, which the API-link rule does not allow.

        Solution: Correct the two faults and narrow the two broad claims

        The editorial and controlled-language passes contributed three further changes:
        one repeated paragraph opening, "idle fraction" used before the section
        introduces it, and "reading" carrying both a clock read and a snapshot.

        Checks run: ./scripts/docs.sh (pass, no new warnings),
        ./scripts/build-site.sh with check-site.mjs over the built site,
        and observability_utilization_smoke, guide_utilization_example, and
        observability_smoke rebuilt and re-run.

      11. bca8ad7f
        Problem: Previewing the built site needs an ad-hoc server command

        scripts/build-site.sh writes the complete site to build/site, but nothing
        records how to serve it. Reading a guide page as it will be published means
        inventing a static-server invocation each time, and picking a port that does
        not collide with a development server already running.

        Solution: Record a launch configuration that serves the built site

        The entry serves build/site on port 8231. It reads the build output and does
        not produce it, so run scripts/build-site.sh first and again after editing
        anything under website/.

        Checks run: served build/site through the entry and loaded the guide page.

      12. 104d406f
        Problem: macOS L1 detection reports efficiency-core capacity

        The macOS body queries the flat hw.l1dcachesize sysctl. On a heterogeneous
        Apple silicon host that name reports the efficiency-core capacity, not the
        performance-core capacity: one 12P/4E host reports 65536 bytes for the flat
        name against 131072 for hw.perflevel0.l1dcachesize. Flyology_Cachelines.
        L1_Data_Cache_Size therefore reports half the performance-core L1d capacity,
        and L1_Data_Cache_Slots derives its slot count from that halved value.

        The reader also assumed every queried name stores a 64-bit value. It read
        each name into one 64-bit object and accepted a short reply, so a 32-bit
        value was correct only because Darwin is little-endian and the object was
        zero-initialized. The per-level names are 32-bit.

        Solution: Prefer the highest performance level and read the reported width

        macOS 12 and later describe a host whose cores are not identical as ordered
        performance levels, where hw.perflevel0 is the highest-performing level. The
        macOS body now queries hw.perflevel0.l1dcachesize and falls back to the flat
        name only on a host that publishes no performance level, such as macOS 11 and
        earlier or an Intel Mac. Querying hw.nperflevels first would add nothing: the
        per-level name exists exactly when the host publishes performance levels.
        Hardware_Cache_Line_Size is unchanged, because Darwin publishes no per-level
        line size and both Apple silicon core types use the same line.

        The public API keeps its Cache_Query_Result surface. Reporting per-level
        geometry is a separate design question, and it should not ride along in a
        detection correctness fix.

        The sysctl reader moves into a new private Flyology_Cachelines.Macos child,
        mirroring the existing Flyology_Cachelines.Linux split between mechanism and
        policy. It requests each name's stored width before reading the value and
        rejects any other width, so a 32-bit name, a 64-bit name, a string, and an
        absent name are all handled without depending on byte order. Failed and
        malformed queries still degrade to Unavailable rather than raising.

        The GNATdoc comments on L1_Data_Cache_Size and L1_Data_Cache_Slots, the crate
        README, and the website cachelines guide now state that a host whose cores are
        not identical reports one core type, and which one each platform reports. A new
        macOS detection test mirrors the Linux one: it exercises the sysctl reader
        directly and checks that the reported capacity is the highest performance level
        the host publishes.

        Checks run: ./flyology_cachelines/scripts/test.sh (the native test now reports
        131072 bytes of L1 data cache on a 12P/4E host, and the new macOS detection
        test passes) and ./flyology_cachelines/scripts/docs.sh (zero GNATdoc warnings).

      13. d3af8647
        Problem: The Linux detection test requires an optional mechanism

        Flyology_Cachelines.Linux_Testing asserts that both Detect_From_Sysconf and
        Detect_From_Sysfs report a value. Only their composition is guaranteed:
        glibc answers _SC_LEVEL1_DCACHE_SIZE and _SC_LEVEL1_DCACHE_LINESIZE from
        CPUID on x86-64, but reports zero on aarch64, where sysfs is the only
        mechanism. Detect already treats sysconf as optional and falls back to
        sysfs, so the test is stricter than the code it covers.

        The test therefore fails on aarch64 Linux with "sysconf cache detection
        failed". CI runs ubuntu-latest on x86-64, where sysconf answers, so the
        failure is invisible there. It reproduces on aarch64 Linux, which AGENTS.md
        tells contributors to prefer on Apple silicon because it is native and
        faster.

        Solution: Require the composition and check each available result

        Run now requires that at least one mechanism reports a value, and checks
        consistency only for a mechanism that reported one. That is what the
        production detector promises: it composes sysconf and sysfs, and returns
        Unavailable only when neither answers.

        Checks run: the crate suite on aarch64 Linux in a container, where the
        detection test now passes, and on macOS, where it is not built.

      14. 04658ed7
        Problem: Linux cache detection describes only CPU 0

        Flyology_Cachelines.Linux reads one L1 data-cache geometry: sysconf answers
        for the calling CPU, and the sysfs fallback reads cpu0. A host whose cores
        are not identical has more than one geometry, and neither mechanism says
        which core the reported one belongs to, or that others exist.

        macOS already publishes ordered performance levels, so the macOS body can
        prefer the highest-performing one. Linux publishes per-CPU descriptions and
        no single ordering, so the equivalent information has to be derived before
        any public per-core-type query can work on both platforms.

        Solution: Group CPUs into core classes and record what ordered them

        Detect_Core_Classes enumerates the CPUs the host lists as present, reads
        each one's L1 data-cache geometry and capacity, groups CPUs reporting
        identical values into a class, and counts each class.

        Classes are grouped on capacity and geometry together. Grouping on geometry
        alone merges two core types that happen to share an L1 data-cache size,
        which real designs do.

        Ordering uses whichever key separates the classes, and Core_Classes reports
        which one did, so a caller can tell an authoritative order from an inferred
        one:

        - Host_Reported: the kernel's per-CPU capacity values separated them.
        Capacity is the scheduler's own measure of relative CPU performance and
        accounts for microarchitecture and clock. Architectures selecting the
        generic topology code publish it under cpuN/cpu_capacity.
        - Inferred: no capacity separated them, so they are ordered by descending
        L1 data-cache capacity. That holds on current hybrid parts and carries
        no meaning on a host whose classes differ some other way. x86-64 does
        not publish capacity, so its hybrid parts land here.
        - Unordered: fewer than two classes, or nothing separated them.

        Cores and CPUs are counted separately. SMT siblings share one L1 data cache,
        so the cache's sharing list identifies which CPU represents a physical core.
        Counting logical CPUs as cores overstates a 24-core host with two threads
        per core by a factor of two.

        Detection fails closed. A missing or malformed CPU list leaves only CPU 0 to
        enumerate, enumeration is bounded, a CPU whose description cannot be read is
        skipped, and a host reporting more classes than the table holds reports none
        rather than a table that silently omits a class.

        Detect_Core_Classes takes the CPU root as a parameter defaulted to the real
        sysfs path. Grouping, ordering, and the SMT distinction cannot be reached on
        a uniform test host, so the detection test drives them with committed
        fixture trees: two classes separated only by capacity, two classes separated
        only by geometry with the smaller listed first, SMT pairs sharing one cache,
        and a CPU list with a gap.

        Nothing calls Detect_Core_Classes outside the test yet. The public
        per-core-type query, and the elaboration cost of walking every CPU, belong
        to the change that adds that query.

        Checks run: the crate suite on aarch64 Linux in a container and on macOS.
        Detection was also replayed against captured CPU descriptions from a 48-CPU
        x86-64 host with two threads per core, which reports 24 cores against 48
        CPUs and no capacity, and from an 80-CPU aarch64 host, which reports 80
        cores against 80 CPUs and a published capacity.

      15. ba8438da
        Problem: Cache queries cannot name a core class

        Flyology_Cachelines reports one L1 data-cache capacity. A host that combines
        core types has one per type, so a single value silently describes whichever
        type the platform body happened to pick and gives a caller no way to ask
        about the others, or to learn that others exist.

        The two platforms also disagreed. macOS reported the highest performance
        level, while Linux reported whichever cache its own mechanism described:
        sysconf for the calling CPU, sysfs for cpu0. The same call therefore meant
        different things on the two platforms.

        Solution: Make the core class an explicit parameter of every cache query

        Core_Class names one class of cores that report a single cache geometry.
        Core_Class_Count reports how many the host distinguishes, Core_Class_Cores
        and Core_Class_CPUs describe each one, and L1_Data_Cache_Size and
        L1_Data_Cache_Slots take the class they describe. The parameter defaults to
        Fastest_Core_Class, so existing calls keep compiling and now mean the same
        thing on both platforms: the class the host ranks highest.

        Core_Class_Ordering reports what produced that rank, because it is a host
        fact on some platforms and the crate's inference on others. macOS performance
        levels and the Linux per-CPU capacity values are Host_Reported. A host
        publishing no rank is Inferred, ordered by descending L1 data-cache capacity.
        Fewer than two classes is Unordered.

        Cores and CPUs are reported separately. Sibling CPUs under simultaneous
        multithreading share one core's L1 data cache, so a 24-core host with two
        threads per core reports 24 cores and 48 CPUs in one class.

        Hardware_Cache_Line_Size takes no class. macOS publishes no per-class line
        size, and the core types of current heterogeneous parts share one line size,
        so a per-class query would have one answer to give.

        The host is now inspected on first use rather than during elaboration.
        Describing every class means reading one description per CPU on Linux, which
        measures 14 ms for 48 CPUs and 24 ms for 80. A program that links this crate
        and never asks about the host should not pay that at startup. The inspection
        is idempotent, so a race on the first query can duplicate work but cannot
        produce a value neither caller computed; the ready flag is atomic and is set
        after the result is stored.

        Flyology_Cachelines.Platform now answers one Detect call describing the whole
        host, and the root package body owns the single memoization. The two Linux
        bodies share one translation and differ only in what they report when sysfs
        describes nothing: the x86-64 body can still read the calling CPU through
        CPUID. Flyology_Cachelines.Linux drops its own class and ordering types in
        favour of the public ones, so the crate has one Core_Class.

        The website cachelines guide is corrected alongside the API. Adding the Class
        parameter changed the generated GNATdoc anchors for L1_Data_Cache_Size and
        L1_Data_Cache_Slots, so the guide's links to them became dangling fragments;
        both now point at the regenerated anchors. The guide also claimed detection
        happens during package elaboration, which is no longer true. The new entities
        are linked to their generated entries on first mention.

        Checks run: the crate suite on macOS, where a 12P/4E host reports two
        host-ordered classes of 131072 and 65536 bytes across 12 and 4 cores; on
        aarch64 Linux in a container; and on an x86-64 Linux host with 24 cores and
        two threads per core, which exercises the CPUID body and reports 49152 bytes
        across 24 cores and 48 CPUs. GNATdoc builds with no warnings.

      16. 9782c81b
        Problem: The shared L2 cache is not reported

        Flyology_Cachelines reports L1 but not L2, so a caller sizing a working set
        against the level it will actually spill into has nothing to read.

        The flat sysctl this crate would naturally have used is wrong in the same way
        hw.l1dcachesize was, and by a larger factor. On a 12P/4E Apple silicon host
        hw.l2cachesize reports 4194304, the efficiency cluster's cache, against the
        performance cluster's 16777216. Adding L2 before core classes existed would
        have reproduced the original defect at four times the size instead of two.

        Reporting a capacity alone would also mislead. L2 is rarely private: that same
        host shares 16 MiB across six performance cores and 4 MiB across four
        efficiency cores, so neither figure is a per-core budget.

        Solution: Report L2 capacity and how many cores share it, per class

        L2_Cache_Size and L2_Sharing_Cores take the same core class as the L1
        queries. A sharing count of one means the cache is private to a core; a
        larger count means the reported capacity is divided among that many cores.
        The GNATdoc on each function points at the other, because reading either
        alone invites the per-core mistake.

        macOS reads hw.perflevelN.l2cachesize and hw.perflevelN.cpusperl2. Linux
        reads the level 2 entry of each CPU's cache description, counting the CPUs
        its shared_cpu_list names. Both counts arrive as logical CPUs and become core
        counts through the class's own threads-per-core ratio, so a host with two
        threads per core does not report twice the cores sharing a cache.

        Parsing a CPU list needs more than its leading index, so the Linux body gains
        List_Count, which sums the single indexes and inclusive ranges a list names.
        Describing L2 costs no extra file reads: the level 2 entry is found in the
        same pass over the cache indexes that already locates the level 1 data entry.

        The website cachelines guide gains the same pairing, with both names linked
        to their generated entries.

        Checks run: the crate suite on all three supported targets. A 12P/4E macOS
        host reports 16777216 bytes across 6 cores for its performance class and
        4194304 across 4 for its efficiency class, and the macOS test asserts that
        these come from the performance level rather than the flat name. An aarch64
        Linux host reports 16777216 across 6 cores. An x86-64 Linux host with 24
        cores and two threads per core reports 2097152 across 1 core, where sysfs
        gives 2048K shared by CPUs "0,24"; that run also compiles the CPUID body,
        which builds nowhere else. Fixtures cover a per-class shared L2, an L2 shared
        across SMT siblings, and a private L2. GNATdoc builds with no warnings.

    3. 9782c81b updated to 7be049fcindex 6e2db0ef

      1 source commit

      1. 7be049fc
        Problem: A stalled package mirror hangs CI instead of failing it

        The two OpenSSL install steps in the test job carried no bound, so a mirror
        that stops answering leaves apt waiting rather than returning an error. On
        2026-08-19 run 32297071503, job 96211136305 sat on "Install OpenSSL 3 on
        Linux" for 32 minutes and had to be cancelled by hand; it was the only check
        blocking PR #49. Its log shows apt-get update fetching noble-security
        InRelease at 20:13:04 and producing no further output until cancellation. The
        macOS half of the same job passed, so nothing was wrong with the tests.

        Left alone the job would have run to GitHub's six-hour default. Nothing else
        in either workflow was bounded either: the checkout, the Alire install, the
        index configuration, the Java and TLA+ downloads, and the GNATdoc install all
        reach the network under the same default, and no job in this repository
        declared a timeout at all, unlike the sibling repositories.

        Solution: Bound every job and every step that reaches the network

        Each job now declares a timeout-minutes, and so does each step that fetches
        something. The bounds are generous multiples of what healthy runs measure
        over the last 60 successful runs of each workflow, so they can only fire on a
        stall. Jobs: test observes at most 17 minutes on macOS and 11 on Linux and is
        bounded at 60; proof observes 6 minutes and TLA+ 7, both bounded at 30; the
        pages build observes 69 seconds and is bounded at 20, its deploy 10 seconds
        and bounded at 15. Steps: everything network-touching is bounded at 10
        minutes against observed maxima of 1 to 6 seconds, except the Alire install,
        which downloads the toolchain, observes 100 seconds, and is bounded at 15.

        A step timeout alone would only have converted the 32-minute hang into a
        10-minute one, because the stall is inside a single apt-get update that never
        returns. That command is now capped per attempt with timeout(1) and retried
        twice with 15 and 30 second backoff, so one unresponsive mirror costs a
        retry rather than the job. The install that follows is capped as well but not
        retried: a package that cannot be resolved should fail on the first try. The
        worst case is three 120-second attempts plus a 10-second kill grace, 45
        seconds of backoff, and a 190-second install, which is 10m25s and lands
        inside the 12-minute step bound, so the annotation naming the transient
        mirror is what the log ends on rather than a bare cancellation.

        GNU timeout is used directly rather than scripts/run-with-timeout.sh. That
        helper exists for portability to macOS, and this step is Linux-only.

        The TLA+ download gains --connect-timeout 30 and --max-time 120 alongside its
        existing --retry 3, because curl retries a failed transfer but not a stalled
        one, and --max-time resets per attempt. Four bounded attempts stay inside the
        step's 10 minutes.

        Build, test, proof, and model-checking steps keep no step bound. Their
        duration is workload-dependent, a bound sized for them would be a performance
        budget rather than a stall detector, and the job timeout already covers them.
        Nothing about what is installed, or how anything is built or tested, changes.

        Checks run: both workflows parse. The retry script was extracted from the
        committed YAML and driven under bash -e against stub apt-get invocations for
        five outcomes: first-try success runs one update and one install; two
        failures then success runs three updates and installs; three failures exit 1
        with the annotation and never install; an install failure propagates its exit
        status without retrying; and exit 124, which is what timeout(1) reports when
        it kills a stalled command, is treated as retryable. The real commands were
        then run in an ubuntu:24.04 container on coreutils 9.4, the runner's version:
        the bounded update succeeds, interrupting one mid-flight reports 124, a
        retry after that kill still succeeds rather than inheriting a poisoned apt
        state, and the bounded install still yields OpenSSL 3.0.13 through pkg-config.

        The convention is recorded in AGENTS.md so it holds for new steps, and it
        matches the job-level timeouts already used in flyology-http and
        gnat-patches, whose install steps want the same treatment.

        Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

    4. 7be049fc updated to a53da35dindex b5569962

      1 source commit

      1. a53da35d
        Problem: The allocators dependency accepts any version

        The allocator crate is developed alongside the runtime in this repository and
        released on the same development line, but the dependency on it is declared as
        "*". Nothing stops a dependent from resolving an allocator release built for a
        different line, and the index has been carrying a tighter constraint by hand to
        compensate.

        Solution: Constrain allocators to its development line

        Declare the line the allocator crate actually publishes, so the constraint
        travels with the manifest instead of being reapplied wherever it is indexed.

        Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

    Compare source revisions
    Development update

    flyology_bench 0.1.1-dev

    5 updates: 91d6a0f6 through a53da35d

    Adaptive nanosecond-scale benchmarking for Ada

    Manifest fields
    origin
    Show all 5 updates
    1. 91d6a0f6 updated to 9a24bf68index 510cfcf6

      39 source commits

      1. 40849230
        Problem: DNS smoke depends on hosted-runner timing

        The functional loopback checks use retry intervals too narrow for occasional macOS hosted-runner stalls. An early client exception also waits behind cancellation coordination and loses the operation that failed, leaving only a generic lifecycle assertion.

        Solution: tolerate stalls and report DNS smoke stages

        Use functional smoke deadlines that accommodate runner scheduling, let coordination observe early client completion, and report the execution model and operation stage for unexpected exceptions. The dedicated DNS resilience smoke retains narrow deadline coverage.

      2. 347604c6
        Problem: Codex and Claude usage across the Flyology workspace is difficult to audit

        Session logs are distributed across project checkouts, worktrees, sister
        repositories, and nested agent sessions. Their token counters also contain
        cached input, repeated cumulative records, inherited history, and duplicated
        Claude message entries, making straightforward aggregation inaccurate.

        Solution: add a portable incremental AI usage audit

        Add a self-contained PEP 723 Python script that discovers the workspace from
        its containing repository and scans associated Codex and Claude Code logs,
        including worktrees, subagents, and workflows.

        Deduplicate cumulative and inherited records, categorize base input, cache
        reads and writes, output and reasoning tokens, and estimate API-style costs
        using model-specific pricing. Persist JSON cursors and daily aggregates so
        subsequent runs process only new log records.

        Provide summary, daily, weekly, provider, and model breakdowns with JSON
        output, date filtering, configurable paths and timezone, state rebuilding,
        and integrity diagnostics.

      3. 73925055
        Problem: Flyology website presents Runtime as the umbrella

        The landing page, navigation, guide index, and machine-readable documentation center Flyology Runtime while standalone libraries share the project identity without depending on it. Visitors cannot reliably distinguish the runtime core, runtime-dependent protocol libraries, and independently adoptable components, and several component documentation paths are missing or placed under the wrong section.

        Solution: Present Flyology as the project and Runtime as its core

        Reorganize the landing page around the project umbrella, add focused Runtime and Libraries pages, move Guide, Architecture, and the main API under Runtime, separate standalone documentation from the Runtime guide, link each published component Guide and API, fix the scrollable guide topic rail, and align README, product, design, journal, build assertions, and llms.txt with the same dependency model.

      4. 6cb6887f
        Problem: Flyology package discovery and maturity guidance compete

        The redesigned project pages repeat the experimental label in several nearby locations while the curated Libraries directory has no path to the complete package index. Readers see redundant maturity warnings but cannot easily reach version, dependency, availability, and compiler-build records for every published package.

        Solution: Clarify maturity guidance and link the complete crate index

        Keep experimental status in the primary explanatory context, make constraints and adoption guidance more direct, and link crates.flyology.org from the Libraries introduction, footer, and llms.txt documentation map.

      5. 4738d656
        Problem: The crate index is absent from shared site footers

        Only the Libraries page exposes the complete package catalogue in its footer. Readers arriving on Runtime, Guide, Architecture, Journal, or the project overview have no equivalent utility path to package versions, dependencies, and availability records.

        Solution: Add the crate index to every shared footer

        Place the Crate index utility link first in each hand-written footer, including the journal entry template, while retaining every page-specific navigation link.

      6. 5b7c3925
        Problem: Cancellation promptness is asserted as a per-round wall-clock bound

        Check_Parent_Cancellation_Is_Prompt in tests/task_scope_faults_smoke requires
        every one of 16 rounds to propagate parent cancellation within 5 ms.
        Propagation crosses two lightweight-task wakes, and a contended shared runner
        can deschedule either of them for milliseconds, so the check reports host
        scheduling as often as it reports the mechanism. CI run 32100324387 failed
        this assertion on its first attempt and passed on a rerun of the identical
        commit 71df9ed, whose only change is .github/workflows/pages.yml. Locally,
        96 spinning processes on 16 cores plus nice -n 20 reproduce the failure in
        2 of 30 runs, and 1280 rounds measured under that load put the median at
        78 us with 0.9 per cent of rounds past 5 ms: the mechanism is prompt and the
        bound is reporting the host. A bare pragma Assert also names only a source
        line, so a real regression is indistinguishable from a stalled round.

        Solution: Require most rounds to be prompt, bound the rest, and report them

        The check now measures all 16 rounds, requires at least 10 of them within
        1 ms, and requires no round past a 0.5 s sanity ceiling. That is a stronger
        claim about the mechanism rather than a weaker one. The retired 10 ms polling
        monitor spreads its latency across its period and places about 1.6 of 16
        rounds inside 1 ms, so it clears the new bar about once in two million runs
        against once in sixty-five thousand for the old whole-round 5 ms bound;
        reinstating that monitor put 0 of 16 rounds inside 1 ms and failed the new
        check on all five idle runs. Under the load that failed the old check in
        11 per cent of runs, the new check passed 60 of 60. A failing round set is
        printed to standard error so the next failure names the rounds and their
        latencies instead of only the assertion line.

      7. 857820c4
        Merge pull request #47 from flyology-ada/claude/gifted-sanderson-75002d

        Problem: Cancellation promptness is asserted as a per-round wall-clock bound

      8. 5dfa0d25
        Problem: Broken site links reach main before anything checks them

        The site check that validates local links and fragment targets runs only in
        the Pages workflow, which triggers on a push to main and on manual dispatch.
        No pull-request workflow builds the site, and ci.yml has no site job, so a
        change that breaks a link passes every check a reviewer sees, merges, and
        then fails the Pages build on main. The site stops publishing at the point
        where the mistake is hardest to attribute.

        The hand-written pages carry 457 links into generated GNATdoc entries across
        eleven guide and architecture pages. GNATdoc names each entry by a hash of
        the declaration, so changing a public subprogram's parameters gives it a new
        anchor and silently strands every hand-written link to it. Editing the
        surrounding documentation comment does not, which makes the failure easy to
        miss: prose edits are safe, and a signature change quietly is not.

        Solution: Build and check the site on pull requests

        The Pages workflow now also runs on pull_request. The build job is
        unchanged for a push, and on a pull request it builds the site and runs the
        same link check without touching Pages: configuring Pages, uploading the
        artifact, and the deploy job are all skipped. A pull request therefore needs
        no Pages permission, which also keeps the job usable from a fork.

        Concurrency now groups per ref. One group for every event serialized
        unrelated pull requests behind each other and behind a deploy. Pushes to main
        still share one group and are still never cancelled; a pull request cancels
        its own superseded runs.

        This adds a toolchain and GNATdoc build to each pull request, which is the
        cost of resolving generated anchors: the check can only confirm a fragment
        exists by generating the page that defines it.

        Checks run: the workflow parses, has no tabs, guards exactly the three
        Pages-specific steps, and keeps the link check unguarded. check-site.mjs was
        confirmed to catch this class of breakage against a page carrying one stale
        API fragment, where it reports "missing fragment target" and exits non-zero.
        This pull request triggers the new job, so its own run is the end-to-end
        check.

      9. 252f4fd7
        Problem: Ada programs cannot see the host's memory-node structure

        A machine with more than one processor package attaches memory to each of
        them, and memory attached to the package a thread runs on is reached faster
        than memory attached to another. Nothing in this repository reports that
        structure. Ada itself does not describe it either: System.Multiprocessors
        covers processors and dispatching, and the language has no notion of a
        memory node at all.

        Without it, a program that wants its work near its memory has nothing to
        place against.

        Solution: Adopt flyology_numa as a nested standalone crate that reports it

        The crate reads the host description and reports memory nodes, the
        processors attached to each, firmware-declared distances, per-node memory,
        and processor packages. It does not place memory; that is a separate
        question this crate does not answer.

        Three decisions shape the interface.

        Topology queries are total. A host with no memory-node structure reports one
        node holding every processor, because such a host genuinely has one memory
        domain. Support distinguishes a description that was read from the host from
        that single-domain description. Individual facts a host does not answer use
        the existing variant-record convention with Value_Or, so a caller names its
        own fallback rather than receiving a plausible number.

        Online and permitted nodes are reported separately. A container is shown the
        whole machine's node list while a control group restricts what it may
        allocate on, so the host description alone does not establish permission.
        Allowed_Nodes intersects the description with Mems_allowed_list from the
        process status file.

        Node and processor numbers are the host's own, and sparse. They match sysfs
        paths and numactl output, so a reported number is the number to look up
        elsewhere. To_CPU performs the Ada processor mapping GNAT applies unchecked,
        and declines when the host's numbering has a gap the mapping cannot carry.

        A description this crate cannot read is reported as a shortfall rather than
        guessed at. Support.Complete goes false when any part of the description was
        refused: a node or processor number beyond the represented range, a list
        naming more ranges than the reader holds, an unreadable processor list, or a
        permitted-node list the host named and the reader did not understand. The
        distinction that matters is between a node with no processor attached, which
        is an ordinary memory expander, and a node whose processor list could not be
        read, which is not known to have none. A description that names nodes but
        attaches no processor to any of them is refused outright, because every
        machine has a processor.

        The sysfs reader names the directories it reads instead of assuming them, so
        it is host-independent text processing that compiles and runs everywhere.
        This departs from flyology_cachelines, which keeps all Linux code under a
        Linux source directory and tests only the host it runs on. The interesting
        cases cannot be reached that way: a development machine has one node and a
        container on one is single-node too. Twelve recorded descriptions under
        tests/fixtures cover two packages of one node each, two packages each
        divided into two memory nodes, a node carrying memory with no processor
        attached, sparse node numbering, a control-group restriction, a gap in
        processor numbering, an older host naming only its ordinary memory, and five
        descriptions the reader must refuse or report as incomplete. All are
        exercised on macOS, which has none of them.

        Set algebra lives in its own unit rather than the root body because
        discovery runs during the root package's elaboration and cannot call back
        into the body it is elaborating. Each step of the discovery chain names the
        body it needs with pragma Elaborate, so the ordering does not rest on the
        binder inferring it. Elaborate_All would not serve: its closure reaches back
        through the platform spec to the root body itself.

        A processor list is bounded at one range per processor rather than at 64,
        because a host that enumerates processors round-robin across its nodes gives
        each node a list of single-processor ranges.

        Verified with ./flyology_numa/scripts/test.sh on macOS aarch64 from a clean
        tree: both the host suite and the fixture suite pass, and clean builds of
        the linux, macos, and unsupported platform bodies through the crate's
        host-selection scenario variable emit no warnings, style diagnostics, or
        errors.

      10. 376d2481
        Problem: Flyology_NUMA reports memory nodes but cannot use them

        The crate describes which memory nodes a host has and which processors are
        attached to each. A program that wants its work near its memory can read
        that and then do nothing with it: there is no way to ask that a region's
        pages be drawn from a chosen node.

        Solution: Add Flyology_NUMA.Placement over the kernel's memory-policy calls

        Placement is a separate package from the reporting one because the two fail
        differently. Reading a description always succeeds; acting on one often does
        not. Support reports which of three states applies before anything is
        attempted, and every operation reports its own outcome rather than raising.

        The third state is the one worth having. A host may have no placement
        interface, or it may have one this process is refused. A container sandbox
        commonly refuses these calls while the machine underneath has memory nodes
        that other processes are using, and reporting that as a host without the
        facility would be wrong. Denied is therefore distinct from Unsupported_Host.
        The two are told apart by what the host said about itself rather than by the
        error number alone, because a sandbox may answer a refused call by claiming
        the call does not exist: a host that described its own memory nodes has the
        calls that act on them, so a refusal from such a host is a denial.

        Support is settled on the first call that needs it rather than while the
        package elaborates. A sandbox that answers a refused call by ending the
        process would otherwise end any program that merely links this crate, even
        one that never places memory.

        Apply_To places a range, Apply_To_Thread places what the calling thread
        allocates from then on, Node_Of_Address reports where a page ended up, and
        Permitted_Nodes asks the host afresh rather than reusing what it said
        earlier. A range must begin on a page boundary because placement acts on
        whole pages; an unaligned range is refused before the host is asked.

        Three details of the kernel interface are easy to get wrong and silent when
        got wrong, so each is handled deliberately.

        The node-bit count is decremented by the kernel before the mask is read, so
        passing the number of bits meant would drop the highest node. Placement
        passes one more than that, which names every node this crate represents
        while still asking for only the eight bytes the mask has. Reading the
        permitted nodes is bounded differently again: the kernel refuses a count
        below the number of nodes the host could ever have, counting nodes that are
        merely possible rather than online, so that read uses a buffer covering the
        largest node count Linux can be built for.

        Two policies take no node set, and the kernel rejects either of them when
        one arrives. Passing the set a caller naturally has to hand would therefore
        fail, so the set is dropped before the host sees it and the interface's
        promise that it is ignored is kept.

        The preferred policy takes a single node, not a set. The interface documents
        that only the lowest-numbered node is preferred rather than implying the
        whole set contributes.

        No C library wraps these calls. Their manual pages document a separate
        library's wrappers, not the one every program already links, so they are
        reached through the generic system-call entry point. That entry point is
        variadic, which is one of the reasons this repository admits C, but GNAT's
        variadic convention reaches it correctly without a C file and keeps the
        crate free of one, as flyology_cachelines is.

        Call numbers differ per architecture, and not only in value: the x86-64
        table and the table newer architectures share disagree on the order of
        get_mempolicy and set_mempolicy. Calling by a number from the wrong table
        reaches a working but unrelated kernel service, which is worse than not
        calling at all, so each table is written out separately and an architecture
        whose numbers are not recorded disables placement rather than borrowing
        them.

        That failure is silent by nature, so the host suite has an invariant that
        exposes it: a host that described its own memory nodes has the calls that
        act on them, so reporting no way to place memory means the calls were not
        reached. Building for one architecture with another's table was checked to
        fail on exactly that assertion rather than passing quietly, and passing a
        node set with a policy that takes none was checked to fail before the set
        was dropped.

        Verified on macOS aarch64, x86-64 Linux, and AArch64 Linux. macOS reports
        Unsupported_Host and places nothing. Both Linux architectures report
        Supported and complete every operation: every policy applied to a range and
        to the calling thread, a written page reported on an online node, an
        unaligned range refused, and an empty node set refused for a policy that
        needs one. Builds of the macos, linux and unsupported platform bodies across
        x86-64, AArch64 and an architecture with no recorded table emit no warnings,
        style diagnostics, or errors.

      11. 41e2d423
        Problem: Naming a memory node for an object means placing it by hand

        Flyology_NUMA.Placement acts on an address range. Using it to put an object
        on a chosen node means obtaining page-aligned memory, placing it, carving
        objects out of it, and releasing it afterwards, all in the caller's code and
        all outside the language's own way of saying where memory comes from.

        Ada already has that way: the storage pool of an access type. Nothing here
        supplied one.

        Solution: Add Flyology_NUMA.Pools, a storage pool whose subpools are nodes

        An access type names the pool and each allocation names the node, so where
        an object lives is written at the point it is created rather than arranged
        around it:

        Item : constant Sample_Access := new (On_Node (Arena, Near)) Sample'(...);

        Subpools are the part of the language that fits this. A pool alone would fix
        the node when the access type was declared; a subpool is chosen per
        allocation, which is what naming a node needs to be.

        The pool obtains whole pages from the host rather than taking memory from
        the ordinary heap. Heap memory may begin partway into a page whose remainder
        belongs to something else, and placing that page would move memory this
        crate does not own. Pages are placed before any of them is handed out, since
        placing them afterwards would leave whatever had already been written where
        the host first put it.

        Memory is handed out by advancing through pages already obtained, and goes
        back to the host when a subpool is deallocated or the pool is finalized.
        Freeing a single object does nothing. That suits memory built up and
        discarded together, which is what a node-bound arena usually is, and the
        interface says so rather than implying a general allocator.

        Ownership of the pages is left to the runtime's own teardown rather than
        taken over. The runtime keeps the records it needs to finalize an object
        inside the very pages that object lives in, and a pool that gave its pages
        back first would take those records with them; a pool holding anything with
        finalization would then fail on the way out of its own scope. Deallocating
        one subpool likewise forgets it, because the runtime has already detached it
        by then and a pool that still believed it owned it could never serve that
        node again.

        Only the policies that name a node can be given to a pool. The two that name
        none place nothing on the node the subpool stands for, so a pool built on
        one would report memory placed there that never was.

        Placement_Reached separates a host that placed the memory from one that
        could not, and says which of the two it means: the host accepted the
        request. Under a bound policy that puts the pages on the node; under a
        preferred one the host stays free to draw from elsewhere. Allocation
        succeeds either way, on the reasoning that memory in the wrong place still
        runs while no memory does not.

        A pool is not task safe, and the interface says so. Two tasks allocating
        from one subpool at once can be handed the same address.

        Verified on macOS aarch64, x86-64 Linux, and AArch64 Linux, and inside
        guests built to have several memory nodes, which no machine to hand does.
        scripts/multinode-check.sh boots a two-node guest and a four-node guest
        whose distances are uneven and one of whose nodes carries memory with no
        processor attached, then runs the host suite inside them. It was run on
        both x86-64 and AArch64, each emulating its own architecture, so that the
        placement calls a guest makes are the ones its architecture's table names. Those runs are
        what exercise choosing between nodes at all: memory bound to each node in
        turn and confirmed held by that node, including the node with no processor;
        interleaving spread over every node rather than drawn from one; and a node
        shown further from another than from itself.

        The suite gained cases for the two failures described above, and each was
        confirmed to fail before the change and pass after. Builds of the macos,
        linux and unsupported platform bodies across x86-64, AArch64 and an
        architecture with no recorded placement table emit no warnings, style
        diagnostics, or errors.

      12. a416d8dc
        Problem: The flyology_numa test entry point is not executable

        ./scripts/test.sh runs each crate's own entry point by path, so the file
        has to carry the executable bit. flyology_numa/scripts/test.sh was recorded
        without it and the whole suite stopped there, reporting only that a command
        could not be run.

        Running the script as an argument to a shell, which is what a person does
        while writing one, works either way and hides this.

        Solution: Record the executable bit, as the other crates' entry points do

      13. 550bc612
        Problem: flyology_numa is absent from the site and the API reference

        The crate ships, and nothing outside its own directory says so. It has no
        guide page, no generated API reference, and no entry in the library ledger
        or the machine-readable index. A reader who finds the other standalone
        crates on the site does not find this one.

        Solution: Adopt the crate into the documentation and the site

        The crate now builds its own GNATdoc reference, and the root documentation
        run builds and asserts it alongside the other crates. Publishing it required
        documenting the pool primitives the runtime calls, which had no comments,
        and describing the pool's discriminants in prose: @field names a record
        component, and a discriminant of a private type is neither.

        The package renaming that shortened System.Storage_Pools.Subpools in the
        public part is now in the private part. GNATdoc reported the public renaming
        on every documentation run, and the full name appears twice in the visible
        declarations rather than in every generated page.

        The guide page follows the order a reader needs: add the crate, read the
        node structure, use the permitted nodes rather than the online ones, handle
        a host with one memory domain, place memory, allocate from a node, and read
        distances and packages for what they say rather than what they suggest.

        Every API link on that page was resolved through the generated search index
        rather than by reading the generated markup, which does not put an entity's
        name where a reader of the HTML would expect it.

        The library ledger keeps its alphabetical order, so the new entry is S05 and
        the two entries after it move up.

        Verified with ./scripts/docs.sh, which builds the reference with no
        undocumented-entity warnings, and ./scripts/build-site.sh followed by the
        site checker, which reports 144 HTML files and 201 total files. The crate's
        own suite still passes.

      14. ae1e3ddf
        Problem: The landing page does not list flyology_numa

        The project map in the hero names each standalone library, and the
        catalogue below it links each one. Both lists stop at the crates that
        existed before this one. A reader who arrives at the site and looks for what
        Flyology offers does not learn that the crate exists.

        Solution: Add the crate to the hero project map and the catalogue

        Both lists keep their alphabetical order, so the entry sits between IRI and
        SIMD. The catalogue entry links to the guide, as the entries for the other
        crates with a guide on this site do.

        Verified with ./scripts/build-site.sh and the site checker, and by fetching
        the built pages: the hero and catalogue both list the crate, and all 39
        internal links on its guide page resolve.

      15. aa8b12ed
        Problem: The numa guide explains how before it explains what

        The page opens with a short definition in a callout and then goes straight
        to adding the crate. A reader who does not already know what a memory node
        is learns the interface before the reason for it, and a reader who does know
        still gets no picture of the machine the crate describes.

        Solution: Open with a section that explains memory nodes and draws one

        The section states what changes when a machine has more than one processor
        package, draws a two-node machine with a local and a remote access, and says
        plainly when placement is worth doing at all: a program that fits in cache,
        or one that allocates little, does not gain from it. The callout it replaces
        said less.

        The diagram uses only the classes the figure context defines. An earlier
        draft used a class that context does not style, and SVG then fell back to a
        solid black fill. That reads as deliberate against a dark background and
        wrong against a light one, which is how it survived a first look.

        Both themes were checked by computed style rather than by eye. The
        containers take the page's own surface and border colours, so they follow
        the theme instead of fighting it.

        Verified with ./scripts/build-site.sh and the site checker.

      16. 7b70cbf6
        Problem: Allocation algorithms are coupled to Flyology shared-memory policy

        Buddy, best-fit, and TLSF live inside the main package hierarchy, so bare-board runtimes cannot reuse them without also accepting Flyology identity, mapping, and shared-memory concerns.

        Solution: Extract allocation algorithms into a standalone crate

        Add flyology_allocators 0.1.0-dev with caller-owned regions, timed contention retries, native and ARM bare-board verification, and optimized memory primitives. Keep magic and schema policy in a thin Flyology adapter, pin the new crate from Flyology, and update integration tests and documentation.

      17. 7bf86246
        Problem: Standalone allocator performance has no focused comparison

        The extracted algorithms lack a reproducible benchmark against the platform allocator, making hot-path regressions and algorithm tradeoffs difficult to measure.

        Solution: Add a dedicated flyology_bench allocator shootout

        Add an optional hosted benchmark subcrate with fixed-size and fragmented-churn workloads comparing malloc, Buddy, Best-Fit, and TLSF in balanced paired rounds. Keep benchmark dependencies outside the bare-board crate closure and document release and smoke workflows.

      18. be44ac54
        Problem: Buddy allocator repeats checked address work on every node

        Profiling shows recursive Buddy allocation and release spend most of their time rebuilding and validating structure-relative node addresses. Release also validates each handle twice before its first mutation, making small allocation cycles substantially slower than the other standalone algorithms.

        Solution: Cache the validated Buddy node-table binding

        Retain the process-local node-table base in the attached view after validating its complete native range, use bounded node-relative addressing on hot paths, clear the binding on detach, and remove the redundant release validation while preserving validation before mutation.

      19. 283d5e71
        Problem: TLSF repeats checked address work on every metadata field

        Profiles of fixed allocation cycles show TLSF spending most of its time in free-list insertion and removal, block initialization, and handle validation. Each logical operation repeatedly recomputes and validates the same block base before touching adjacent scalar fields, leaving the constant-time algorithm dominated by address machinery.

        Solution: Reuse validated block bases across TLSF hot paths

        Validate each referenced block extent once, carry its process-local base through list mutation, splitting, coalescing, and handle release, and keep stored link, size, generation, state, and bitmap checks intact. Avoid a redundant ready-state check while the arena guard is held and replace size-class division by its exact power-of-two shift.

      20. e9199d66
        Problem: Best-fit allocator repeats metadata work on hot paths

        Profiling shows fixed-layout address validation, duplicate split and coalesce writes, and repeated AVL balance reads dominate Best-Fit allocation and release. This leaves both fixed cycles and fragmented churn substantially slower than necessary.

        Solution: Streamline checked Best-Fit metadata operations

        Cache the last complete block-header location in the local view, use a fixed-field address path that retains attachment and complete-header bounds checks, avoid tree metadata writes that insertion immediately replaces, and compute AVL balance inputs once per ancestor. The stored layout, persisted validation, guard behavior, handle generations, and bare-board dependency boundary remain unchanged.

      21. 05d2eb83
        Problem: Allocator benchmarks leave imported algorithms unoptimized

        The benchmark project selects release switches only for its own sources. Imported flyology_allocators units are compiled without optimization, making comparisons against the optimized system malloc misleading and overstating allocator hot-path costs.

        Solution: Force a clean optimized benchmark closure

        Build the benchmark and all imported Ada sources through gprbuild with explicit O3, debug symbols, Ada 2022, warnings, and validity checks. Document why the runner must apply switches across project boundaries.

      22. 77e1d163
        Problem: Benchmark arrays use obsolete aggregate syntax

        GNAT reports parenthesized array aggregates as obsolescent when the benchmark closure is compiled as Ada 2022, obscuring useful build diagnostics.

        Solution: Adopt Ada 2022 bracketed array aggregates

        Convert Flyology Bench array initializers and expressions to bracket syntax while retaining parentheses for record aggregates. Keep the obsolescent warning category enabled so future occurrences remain visible.

      23. 77ce4c04
        Problem: TLSF eagerly coalesces every released block

        Release repeatedly discovers physical neighbors and removes and reinserts free-list entries even when the next allocation can reuse the same size class. This makes steady fixed-size and churn workloads pay fragmentation-recovery costs on every operation.

        Solution: Defer TLSF coalescing until allocation requires it

        Return released blocks directly to their size class and perform a bounded, checked physical coalescing pass only after a normal TLSF search misses or before destroying an empty arena. Preserve boundary tags and bitmap/list validation, and cover adjacent runs, allocated gaps, attachment, stale handles, and complete teardown with adversarial tests.

      24. 562bdd61
        Problem: TLSF still advertises eager constant-bound behavior

        Lazy coalescing makes worst-case allocation linear and no longer joins neighbors during release, but both capability records and package comments retain the eager algorithm contract. Flyology also reuses the eager persisted identity even though version 2 readers reject valid adjacent free blocks produced by the new implementation.

        Solution: Publish the lazy TLSF contract and identity

        Report the linear worst-case search and deferred release coalescing in standalone and Flyology packages, document the miss-triggered pass, and advance Flyology TLSF to version/schema 3 so cross-version attachment fails at the immutable header. Add standalone capability coverage and a Flyology regression that rejects the complete eager identity.

      25. 288b03a2
        Problem: Best-fit repeats split and merge work on exact reuse

        Profiling shows fixed-size allocation cycles spend most of their Best-Fit time splitting a large free block during allocation and immediately removing and coalescing its remainder during release. Fragmented churn repeats related AVL maintenance even when the same physical block can be reused directly.

        Solution: Defer Best-Fit coalescing until allocation needs it

        Index released blocks directly for exact-size reuse. Before reporting exhaustion, validate the complete physical chain, coalesce every adjacent free run, repair boundary links, and retry the AVL search. Accept the resulting persisted representation on attachment, canonicalize empty arenas during destruction, report the resulting linear worst-case search capability, and cover adjacent frees, alternating gaps, stale handles, attachment validation, and teardown.

      26. 41578832
        Problem: Flyology Best-Fit identity permits incompatible lazy images

        Deferred coalescing leaves adjacent free blocks as a valid persisted Best-Fit state. The earlier eager reader rejects that state, but Flyology still advertises the same outer version and schema, so compatibility fails only after entering nested allocator validation.

        Solution: Version the Flyology Best-Fit lazy invariant

        Advance the Flyology-only adapter version and schema while retaining its magic. This makes older readers reject lazy images at the outer identity boundary and keeps standalone allocator metadata free of application identity.

      27. ec813587
        Problem: Best-Fit identity transition lacks Flyology coverage

        The lazy Best-Fit adapter advances its persisted version and schema, but the Flyology data-structure smoke test neither proves rejection of the eager version-2 identity nor reflects the linear fallback and deferred-coalescing capabilities.

        Solution: Exercise the Best-Fit version-3 boundary

        Temporarily replace a live Best-Fit arena outer identity with the version-2 values and require attachment to fail closed, then restore the image. Assert the truthful lazy-coalescing capabilities for both Best-Fit and TLSF.

      28. e1315591
        Problem: Buddy eagerly rebuilds the same free hierarchy

        Small allocation cycles repeatedly collapse a released leaf to the root and split the same path on the next allocation. Profiling shows those release stores and recursive rebuilding dominate Buddy's fixed-size cost.

        Solution: Coalesce Buddy trees only when allocation needs it

        Keep released nodes in the retained split tree, compact free subtrees before a search reports genuine exhaustion, and compact before empty-arena destruction. Add adversarial coverage for half-tree and root reconstruction plus stale handles, and expose the lazy-coalescing capability accurately.

      29. 4ad89a24
        Problem: Lazy Buddy reuse still traverses the retained tree

        After deferring coalescing, profiling shows fixed-size Buddy allocation is dominated by walking the same split path. Fragmented churn also revisits released orders even though the releasing view already knows a suitable free node.

        Solution: Cache one validated free node per Buddy order

        Keep process-local node hints in each attached view, validate persisted state before every hinted reuse, and discard all hints during coalescing and detach. Preserve the persisted layout and fall back to the complete tree for stale or missing hints; cover stale hints across independently attached views.

      30. 22998f64
        Problem: Lazy Buddy metadata boundaries are incomplete

        Buddy still advertises logarithmic eager-coalescing behavior, an eager Flyology reader can attach a retained all-free split tree and falsely report exhaustion for a parent-sized request, and Destroy may release its guard after a partially failed coalescing pass without poisoning the image.

        Solution: Harden lazy Buddy capabilities and lifecycle handling

        Advertise linear miss search and deferred coalescing, advance only Flyology's outer Buddy identity to version 3, and verify the retained two-leaf compatibility case. Check that an arena is empty before Destroy mutates it and poison any coalescing failure. Compile the standalone project as Ada 2022 for bracket aggregates and extend standalone and Flyology compatibility tests.

      31. 66888189
        Problem: Allocator guides still describe eager coalescing

        Buddy, Best-Fit, and TLSF now defer coalescing until an allocation miss, but the root, standalone, and website guides still advertise their former fast-path and worst-case behavior. The stale prose also describes a process-shared guard even though the standalone algorithms are usable with arbitrary caller-owned storage.

        Solution: Document lazy coalescing and view-scoped state

        Describe each successful lookup and miss-triggered coalescing path, report the resulting linear worst-case bound, and use attached-view terminology. Record that stored geometry remains stable while the valid state contract changes and Flyology adapters use version-3 identities.

      32. 94cd5b57
        Problem: Lazy allocator correctness lacks an executable model

        Buddy, Best-Fit, and TLSF now retain free structure on release and coalesce on allocation misses. Behavioral tests cover examples, but no bounded state-machine review checks shared guard ownership, block partitions, index publication, stale view hints, generation-stamped release, false exhaustion, or operation completion across interleavings.

        Solution: Model guarded allocator transitions in TLA+

        Add a parameterized extraction for the three algorithms with policy-specific splitting and selection, TLSF bin and bitmap state, Buddy view-local hints, lazy coalescing, retry, generations, and fairness. Add safe TLC configurations plus required false-exhaustion, stale-hint, stale-bitmap, stale-release, and nontermination counterexamples, wire them into the authoritative runner, and document the production mapping and abstraction limits.

      33. 4dc3e5c0
        Problem: Allocator models can drift from Ada transitions

        The bounded Buddy, Best-Fit, and TLSF models establish safety and liveness for their extraction, but review alone does not detect when persisted metadata, view-local hints, generations, handles, or size-class computations diverge from the standalone kernels.

        Solution: Compare canonical Ada and TLC allocator traces

        Add test-only private-state observers and bounded public-operation traces for all three kernels. Model the same traces in TLA+, compare every operation-boundary snapshot byte-for-byte in the authoritative runner, require no-retry liveness counterexamples, and run the conformance boundary in CI while retaining standalone ARM cross-build isolation.

      34. 54d77f0f
        Problem: allocators lack a slab and span policy

        Solution: add a standalone bitmap-slab and contiguous-span allocator, bridge it into Flyology, benchmark it against the existing policies and malloc, and cover its bounded state machine with positive and deliberately broken TLA+ configurations.

      35. 239aa004
        Problem: slab slot reuse lacks a publication edge

        Solution: publish the affected 32-bit bitmap word with release ordering and acquire it before validating the slot generation. Add bounded safe and deliberately broken TLA+ visibility models so TLC reproduces the former stale-handle acceptance.

      36. 195b83bf
        Problem: large span validation trusts the head extent

        Solution: add a corruption test that makes one large-span head claim its neighboring live allocation, then validate every head and tail descriptor field before reporting capacity or allowing release to mutate the claimed extent.

      37. 7a7bc16f
        Problem: The site does not list flyology_allocators

        The hero project map, the standalone catalogue, the library ledger, and
        llms.txt each name every standalone crate. This branch adds a new one, and
        all four lists stop at the crates that existed when the branch was written.
        A reader who arrives at the site and looks for what Flyology offers does not
        learn that the crate exists.

        Solution: Add the crate to the hero map, catalogue, ledger, and llms.txt

        Every list keeps its alphabetical order, so the entry sits first among the
        standalone crates and the ledger indices shift from S01..S07 to S02..S08.

        The crate publishes neither a guide page on this site nor a generated API,
        because scripts/docs.sh does not build one and flyology.gpr excludes the
        crate from documentation. The entries therefore link to the source tree
        only, as the Flyology QUIC entry already does for the same reason. Adding an
        api/flyology_allocators/ link would fail the site checker.

        Verified with ./scripts/build-site.sh and the site checker, which passes on
        141 HTML files, and by grepping the built pages: the hero, catalogue,
        ledger, and llms.txt all name the crate.

      38. 7dc419f2
        Problem: The data-structures guide links to pages GNATdoc no longer emits

        This branch turns Allocation_Algorithms.Buddy, Best_Fit, and TLSF from
        documented packages into generic instantiations of Allocation_Algorithms
        .Contract. GNATdoc emits no unit page and no declaration anchor for an
        instantiation, so the three API links the guide carries for them now resolve
        to nothing. main gained a site link checker after this branch was written,
        so the Pages workflow reports all three and fails.

        Solution: Present the three instantiations as code rather than links

        AGENTS.md asks that the first explanatory mention of a public entity link to
        its verified generated GNATdoc unit or declaration entry. No entry is
        generated for these three, so there is nothing to link, and pointing them at
        the kernels or at Contract would name a different entity than the prose
        does. The surrounding Arenas, Contract, Allocation_Capabilities, and View
        links are unaffected and still resolve.

        Verified with ./scripts/build-site.sh and the site checker, which now passes
        on 141 HTML files and 198 total files with zero problems.

      39. 9a24bf68
        Problem: The data-structures guide omits the slab/span allocator

        This branch adds Allocation_Algorithms.Slab_Span as a fourth arena allocator
        and says so in the README, but the guide section that tells a reader how to
        choose one still presents three. It names three adapters, describes three
        policies, gives three decision rows, and twice states that all three share
        one metadata guard. A reader choosing an allocator from this page does not
        learn the fourth exists, and the two counts now contradict the README.

        Solution: Describe slab/span alongside the other three and correct the counts

        The introductory paragraph names the adapter and states its shape: bitmap
        slots in fixed runs for small requests, contiguous runs for larger ones, with
        descriptors and generation tables outside the managed bytes. A decision row
        gives the selection rule and the reclamation behavior a caller can observe:
        requests up to half the configured run size take a generation-stamped slot,
        larger requests reserve whole runs, release keeps an emptied slab indexed for
        reuse, and a miss reclaims empty slabs to obtain the run or span it needs.

        The row also states that the run size is an allocator quantum rather than an
        operating-system page, because the name invites the opposite assumption.

        The half-run threshold matches the kernel, which sends a request to a slab
        class when Requested <= Run_Size / 2 and to a span otherwise. Both "all
        three" counts become four. The adapter is a generic instantiation, so like
        Buddy, Best_Fit, and TLSF it has no generated GNATdoc entry to link.

        Verified with ./scripts/build-site.sh and the site checker, which passes on
        141 HTML files and 198 total files, and by parsing the built page: tags
        balance and the new row renders between TLSF and the compile-time choice.

    2. 9a24bf68 updated to 60de2c69index 8a8e9de5

      1 source commit

      1. 60de2c69
        Problem: A development pin ships in the published manifest

        flyology.gpr imports flyology_allocators.gpr, and the manifest both declares
        flyology_allocators as a dependency and pins it to the in-repo directory.
        Alire honours pins only in a root crate's manifest, so a consumer resolving
        flyology from the index never receives that dependency. Its solution omits
        flyology_allocators entirely and gprbuild then fails with "imported project
        file flyology_allocators.gpr not found". A crate whose only dependency is
        flyology = "~0.1.1-dev" reproduces it in two lines.

        Nothing in this repository reports the fault, because the pin satisfies the
        dependency for every build performed here. The pin also hid two further
        assumptions that only the in-repo directory could satisfy.

        Solution: Resolve the allocators dependency from the index

        Drop the pin so the declared dependency resolves the same way for this crate
        and for its consumers. The published flyology_allocators 0.1.0-dev is built
        from this repository at the same commit and the same subdirectory, so the
        source reached is identical; only the path by which it is reached changes.

        Configure the organization index in this repository's own workflows. They
        carried the community index alone, because the pin meant no job here ever
        resolved flyology_allocators from an index, and it is published only in the
        organization index. Without that step alr reports an incomplete solution
        naming flyology_allocators as missing.

        Name the excluded documentation project through the imported project rather
        than through a repository path. Documentation.Excluded_Project_Files listed
        flyology_allocators/flyology_allocators.gpr, which resolved only while the
        crate sat in this working tree; as a dependency its project lives in the
        Alire build tree under a content hash. Flyology_Allocators'Project_Dir asks
        the imported project where it is, so the exclusion holds wherever the
        dependency is deployed and the allocator packages stay out of this crate's
        generated API, where they would otherwise be documented twice.

        Record the rule that produced the fault in the agent guide: no committed
        pins in a crate manifest, alr pin in the consuming workspace for unpublished
        work, and a declared dependency must resolve from the index. Name the
        gprbuild error there too, since that is where the fault appears and it names
        a project file rather than a crate.

    3. 60de2c69 updated to 9782c81bindex 75a836be

      16 source commits

      1. aeb10612
        Problem: The site does not list Flyology RDF

        The hero project map, the standalone catalogue, the library ledger, and
        llms.txt each name every component. Flyology RDF publishes a website, a
        guide, and three generated API references at rdf.flyology.org, but the name
        appears nowhere in this repository. A reader who arrives at the site and
        looks for what Flyology offers does not learn that the project exists.

        Solution: Add the project to the hero map, catalogue, ledger, and llms.txt

        flyology_rdf depends on flyology_iri only. It needs no runtime preparation
        and starts no tasks, so it belongs with the standalone libraries. Every list
        keeps its alphabetical order, so the entry sits between Flyology NUMA and
        Flyology SIMD and the ledger indices shift from S07..S08 to S08..S09.

        The ledger and llms.txt entries carry all three generated references, as the
        Flyology Postgres entries already do, because the project site treats the
        Notation3 and SPARQL APIs as first-class navigation.

        The llms.txt project-structure summary also omitted Flyology Allocators and
        Flyology NUMA, which the same file already listed further down. Both names
        join the summary here.

        Verified with the website-kit site checker, whose output is unchanged from
        the pre-change baseline, and by rendering the pages: the hero, catalogue,
        and ledger all name the project. The six linked URLs return 200.

      2. 2188ee0d
        Problem: The project map announces its framing and then hides the components

        The figure caption claimed "One project, two adoption paths" above two cards
        that already carry the same fact in their labels, so the caption restated
        what the diagram shows. The two card subtitles were not parallel either:
        "Core component" named a role while "No runtime dependency" named a
        dependency, so neither pair member helped a reader compare the paths.

        The component names below them were plain list items. A reader who found the
        name that matched the problem had no way to reach the component from the
        diagram and had to scroll to the catalogue to find the same name again.

        Solution: Drop the caption, make the subtitles parallel, and link the names

        The subtitles now read "Prepare the runtime" and "Add a crate", which state
        the two adoption paths as the actions they are. The figure keeps an
        accessible name through aria-label, and the figcaption rule leaves the
        stylesheet with the element it styled.

        Each component name becomes a link to its best available destination, which
        is the destination the catalogue below already uses: the project site where
        one exists, then the guide, then the generated API, then the source tree.
        The pill moves from the list item to the anchor so the whole badge is the
        hit target. Links open in a new tab and carry no underline, as requested, so
        hover brightens the border and adds a faint fill instead. Each list states
        the new-tab behavior once in its aria-label rather than repeating it in
        twelve hidden spans.

        Verified by rendering the page: every badge computes text-decoration-line
        none and cursor pointer, and the hovered badge is distinguishable from its
        neighbors. The site checker reports one new line against the baseline,
        api/flyology_debug/ from the new Debug badge, which resolves once
        scripts/docs.sh generates the GNATdoc output that this partial build omits.

      3. 5dfd5d36
        Problem: Nothing coordinates tools that need exclusive CPU capacity

        Two measurement runs that share a machine produce two wrong answers, and
        neither run can tell that it happened. The problem is not confined to
        benchmarks: a load generator, a soak test, or a profiler makes the machine
        loud, and a benchmark needs it quiet. Both want the same thing from opposite
        directions, and nothing lets them find each other.

        Worse, two runs that each suspend collection when they detect interference
        are symmetric controllers observing each other. Each pauses because the other
        is loading the machine, both then observe quiet, both resume together, and
        both immediately pause again.

        Solution: Specify a host CPU lock convention and implement it

        The convention is named for the resource rather than for benchmarking, so
        that the tools which create load take the same claim as the tools which need
        its absence. Conflict detection is flock and nothing else: liveness is the
        lock itself, so a holder that dies releases with no cleanup path, no stale
        registry entries, and no pid-reuse hazard.

        A machine-wide claim takes LOCK_EX on the claim file; a claim on individual
        CPUs takes LOCK_SH there and LOCK_EX on one file per CPU. Disjoint core-scoped
        claims therefore proceed concurrently while a machine-wide claim excludes them
        all, with no registry and no arbiter. Per-CPU claims are acquired in ascending
        order, because a total order is what stops two callers with overlapping sets
        from deadlocking on each other's partial claims.

        The path is a single deterministic default rather than a writability-probing
        fallback chain. A chain reintroduces the failure it was meant to prevent:
        /run/lock is 1777 on Debian and root-owned 0755 on Red Hat derivatives, so a
        root process and an unprivileged process on one machine would probe
        differently, land on different files, and each conclude it holds the machine.
        $TMPDIR is avoided for the same reason, being per-user on macOS.

        File content is diagnostic and is never consulted to decide conflicts. It is
        still specified and parseable, one key=value pair per line, because a reader
        must be able to name the holder; cwd is included because tool and pid alone do
        not distinguish one checkout or CI workspace from another. Readers open the
        file without locking, since a shared lock would block behind the very holder
        they are trying to identify, and must tolerate content that is empty, stale,
        or half-written.

        A claim is not proof of exclusivity, and the implementation does not present
        it as one. systemd PrivateTmp= bind-mounts a per-service directory over /tmp,
        so two services share every CPU and cannot see each other's claim files; that
        case is detected from /proc/self/mountinfo and reported as namespace-scoped.
        Separate containers are not detectable from inside and need an explicit shared
        path. A path can be proven private but never proven machine-wide.

        Only the C macros live in the native unit. GNAT's C_Variadic_2 convention
        calls open() correctly even on Darwin/AArch64, where variadic arguments are
        passed differently from fixed ones, so the protocol, the file grammar, and the
        /proc reader are all Ada. The convention compiles on every GNAT this crate
        supports, checked against 13.2.2 through 16.1.0 against an alire.toml floor of
        13, so no compatibility shim is carried.

        Verified by building the crate, and by taking claims on disk: the file matches
        the published grammar, parses with awk -F=, is created 0666, and per-CPU files
        are named beside the machine file.

      4. 13b71a5b
        Problem: The CPU gate only proves the host was quiet before warmup

        CPU_Quiescence samples host counters once, before clock characterization, and
        then never looks again. A machine that goes busy halfway through collection
        produces a result that reads as clean, and nothing in the measurement, the
        console card, or the machine-readable output says otherwise. The gate's own
        documentation admits it "cannot prevent new load from arriving after
        collection begins", and until now that was the end of the story.

        The obvious repair is not available either. Host utilization cannot simply be
        compared against a limit during collection the way the preflight does it,
        because by then the benchmark thread saturates a core and every sample would
        trip the limit.

        Solution: Watch for foreign load during collection and say what was found

        Foreign load is host busy time minus this process's own CPU time, so load the
        benchmark itself creates is correctly not foreign. The estimate scales the
        host busy ratio by wall time rather than converting ticks, so the platform
        tick length never enters the arithmetic. Cross-checked against top on a loaded
        machine, the two agree to within 0.1 percent.

        Three responses form a ladder. Observe records and keeps everything. Retake
        discards the contaminated window and collects it again. Pause waits for the
        host to settle, re-warms, and then collects it again. The re-warm is not
        politeness: a resumed run has cold caches, predictors, and frequency state, so
        without it the first sample after a pause is the outlier the pause existed to
        avoid.

        Nothing adjusts a reported statistic. A skew factor derived from observed load
        would be invented data, because the cost of interference depends on whether
        the contention is an SMT sibling, a shared cache, memory bandwidth, or another
        socket, and the same foreign share can mean no slowdown or a large one. Runs
        are annotated or repaired, never corrected.

        Observation happens between timed samples over windows of whole collection
        units, where a unit is one sample, one comparison pair, or one balanced
        multi-way round. A response therefore never splits the two halves of a pair
        and never lands mid-round, where it would spread interference unevenly across
        the cases a round exists to compare fairly. Windows carry a margin over the
        configured minimum: sized to only just reach it, ordinary batch jitter drops
        them below it and they silently degrade to observation. Host counters are
        tick-based, so a window that still falls short is recorded but never acted on.

        Discarding a window rolls back what the window changed. Per-sample values are
        written by index and survive a retake intact, but the position tally of a
        comparison pair and the process-telemetry summaries are running sums, so a
        discarded pass gives them back. Without that, a run with eighteen retained
        samples and twenty-four retakes would report elapsed time and an average CPU
        share covering forty-two samples, most of which were thrown away.

        Budgets degrade rather than abort. An exhausted retake or pause budget
        continues under Observe and reports it, and paused time is excluded from
        Maximum_Sampling_Time because waiting for the host is not collection.

        Placement is optional and sharpens attribution: with a strict binding every
        other CPU's busy time is foreign outright, and the placed CPU's share is its
        busy time minus the placed thread's own. SMT siblings join the watched set,
        because a process saturating the sibling of the placed CPU slows the
        measurement while leaving the placed CPU's own share clean, which makes
        sibling-blind core-scoped observation worse than host-wide observation rather
        than better. Placement is Linux-only in practice; Apple Silicon implements no
        thread affinity and rejects every request, so the Host_Control documentation
        no longer describes Darwin placement as merely advisory.

        Placement binds only the calling thread, so another thread of this process can
        occupy a watched CPU, where its time is indistinguishable from foreign load.
        Each window therefore reads process CPU as well as thread CPU, and their
        difference bounds how much of the watched capacity those threads could account
        for. Once that bound exceeds the configured foreign limit, the core-scoped
        answer can no longer address the question the limit asks: the run drops to
        host-wide observation, which is well defined for a multi-threaded process, and
        reports Attribution_Diluted. Otherwise a scheduler benchmark run under
        placement would spend its retake budget discarding samples over load it
        created itself. The window that reveals the dilution is discarded rather than
        recorded, because its value was computed under the attribution being
        abandoned.

        The direction of that fallback is deliberate. Core-scoped attribution
        subtracts only the placed thread, which over-reports interference when other
        threads share the watched CPUs; subtracting the whole process instead would
        deduct time our threads spent on CPUs outside the watched set, under-report
        foreign load, and let contaminated data pass as clean. Over-reporting shows up
        in the retake and contamination counts; under-reporting shows up nowhere.

        The host CPU claim is taken before the preflight gate, since waiting for a
        quiet host and then blocking on the claim leaves the quiet verdict stale.

        Everything observed reaches the console card, the CSV schema, and the JSON
        object. That visibility is the point: a run that had to repair itself must say
        so, or a heavily repaired result reads as a quieter machine than the one it
        ran on.

        Verified with ./scripts/test.sh on Darwin/aarch64 and in an Ubuntu 24.04
        container on Linux/aarch64, and under qemu-system-aarch64 across four CPU
        topologies. Core-scoped attribution asserts that it closed an observation
        window, so the thread-CPU probe it depends on cannot fail silently. Two
        assertions were checked against builds that defeat them: one with sibling
        collection disabled fails the sibling assertion under cores=2,threads=2 and
        passes without SMT, and one with the dilution check disabled fails the
        fallback assertion while a task of the test's own process burns CPU. Retake
        and pause are driven by a spawned process, because load raised inside this
        process is its own CPU time and is subtracted by design.

      5. 845bdaca
        Problem: The new guide section ignores the site's writing rules

        website/AGENTS.md governs hand-written pages under guide/**. The interference
        section met none of its API-link requirements and several of its style rules.

        Every public entity it introduced went unlinked: Interference, Placement,
        Host_Lock, the three Interference_Response literals, Maximum_Retakes, Window,
        Rewarm_Time, Maximum_Foreign_CPU_Percent, Include_Siblings, Require_Strict,
        Attribution_Diluted, and Environment. The same page already links
        CPU_Quiescence, Stable_Time, and Timeout, so the new section also read
        inconsistently against its own neighbours.

        Solution: Link the API entities and apply the three prescribed reviews

        The three reviews ran in sequence and are labelled here, since separate review
        agents were unavailable.

        Technical. "Foreign load is host busy time minus this process's own CPU time"
        held only without placement, because core-scoped attribution subtracts the
        placed thread rather than the whole process; the sentence now says so, and the
        placement paragraph states which CPUs the harness measures. "The re-warm is
        required" overstated a configurable field, so the text names Rewarm_Time and
        says what a zero value leaves behind. "When the difference exceeds the
        configured limit" named neither the limit nor the compared quantity, which
        also left Maximum_Foreign_CPU_Percent unlinked. Two harnesses that both pause
        do not deadlock as claimed; they alternate between pausing and resuming.

        Editorial. "This matters most" and "Without it" both referred back to
        something unnamed. Both now name their subject.

        Controlled language. "Sharpens attribution" was figurative and is now
        "narrows attribution to the placed CPU and its SMT siblings". "A run that
        repaired itself reports that fact" personified the run; the report is the
        actor, and it states counts.

        Verified with ./scripts/build-site.sh and the site checker, which passes 144
        HTML files. All fourteen API links resolve to an existing anchor in the
        generated GNATdoc output, and each target matches the entry the API search
        index gives for that entity. No sentence in the section exceeds the 25-word
        review signal.

      6. edf788ef
        Problem: The guide does not say the host controls are opt-in

        The interference section described three capabilities without saying that a
        run acquires none of them unless it asks. BENCH 07 states that contract for
        the preflight gate, and the page marks the default value of a choice where one
        exists, as it does for Equal_Time and Balanced_Rounds. The new section did
        neither, so a reader could not tell that enabling the watch alone changes
        nothing about the collected data.

        The claim file was also absent. The page named three environment variables but
        not the one path that other tools must agree on, leaving the coordination
        surface a click away in the convention document.

        Solution: State the defaults, the claim path, and the budget interaction

        Observe is now marked as the default response, in the form the page already
        uses. The closing paragraph mirrors BENCH 07: the watch, placement, and the
        host claim are disabled by default, so an existing run acquires no new wait or
        failure condition. The opening sentence calls the watch optional where the
        reader first meets it.

        The claim paragraph names /tmp/host-cpu.lock, the Path field that overrides it
        for one run, and the HOST_CPU_LOCK_PATH variable that overrides it for every
        tool following the convention. An earlier draft named only the variable, which
        implied it was the sole override; the technical review caught that against
        Resolved_Path and Try_Acquire.

        The Window row gains the limit that qualifies it. A window covers whole units,
        so a window spanning many short samples can exceed Maximum_Retakes on its
        first discard. Collection then continues under Observe and reports the
        exhausted budget, which otherwise looks like the response never ran.

        Numeric field defaults are deliberately not repeated here. No other section of
        the page tabulates them, every field now links to its generated entry, and a
        duplicated value is one that can go stale.

        Verified with ./scripts/build-site.sh and the site checker, which passes 144
        HTML files. All fifteen API links resolve to an existing anchor, and each
        target matches the entry the API search index gives for that entity, including
        the ambiguous Path simple name, which resolves to Host_Lock_Policy.Path. No
        sentence in the section exceeds the 25-word review signal, and no entity is
        linked twice.

      7. 4fbe5020
        Problem: The recording smoke test separates its workloads with a delay

        recording_smoke drives two benchmarks from four tasks and asserts that the
        slow benchmark's recorded median wall time exceeds the fast one's. The
        separation comes from delay 0.000_2 against delay 0.000_8. A relative delay
        is rounded up to the host timer tick, and on a Linux kernel with a coarse
        tick both requests wake at the same boundary near 3 ms. A four-task probe
        with no recorder involved shows the first iteration of each task honoring
        the request and every later one landing on the same plateau:

        0.0002 s: 323 3710 2829 2972 3069 2947 ... (us)
        0.0008 s: 1167 3307 2482 3625 2793 3045 ... (us)

        The two recorded medians then arrive at 2.98 ms and 2.99 ms, ordered by
        scheduling noise alone. On Ubuntu 24.04 with GNAT 16.1.0 on aarch64 the
        assertion fails about half the time: 9 of 20 runs on a clean checkout. macOS
        resolves the two delays apart, which is why the test has held there. The
        independent comparison checked two assertions below rests on the same
        separation and fails with it.

        Solution: Separate the distributions by work the workers perform

        Each worker spins a volatile rotate-and-xor accumulator, 20_000 rounds for
        the fast benchmark and twenty times that for the slow one, the idiom the
        file's concurrent PMU-session block already uses. That is roughly 33 us
        against 680 us, a twentyfold gap read by a nanosecond wall clock, so no
        timer resolution enters the measurement. It also costs less than the
        sleeping it replaces: the slow workers take about 14 ms rather than 60 ms.

        The assertion stands, since the ordering is the invariant worth holding, but
        its message now carries both medians so a failure on an unusual host reports
        numbers rather than a verdict.

        Verified on the failing environment, an Ubuntu 24.04 container with GNAT
        16.1.0 on aarch64: 30 of 30 runs pass where HEAD fails 9 of 20 in the same
        container, 20 of 20 under a two-CPU quota, and 10 of 10 with 24 competing
        spinners on that quota. scripts/test.sh passes three times from a fresh
        source export there and once on macOS. A calibration probe over 105 further
        trials across those CPU configurations held the ratio between 14x and 30x
        with no inversions and Relative_Change_Percent positive throughout.

      8. ae5b52d7
        Problem: A group snapshot cannot say whether its event loop is busy

        Flyology.Observability.Group_Snapshot carries thirty fields covering queue
        depths, wait categories, and cumulative counters, but none of them reports how
        much of an event loop's time was spent doing work. Pool imbalance is therefore
        invisible from outside the process: a group with a deep ready queue and a group
        that is idle produce the same evidence once their momentary queue depths match.
        Made_Progress detects a stalled loop but not a saturated one, and its comment
        already records why a per-dispatch clock read was rejected as the answer.

        Solution: Time the poller wait a loop takes when nothing is ready

        An event loop enters Wait_Batch only when its ready queue is empty, so the idle
        path is both the exact complement of the loop's working time and a path a busy
        loop never repeats. The scheduler stamps the wait before releasing the group
        lock and closes it after reacquiring, keeping the in-progress wait in the group
        so an observer adds it rather than charging a long block as busy time. Nothing
        is added to dispatch, context switch, or any other hot path.

        Group_Snapshot gains Uptime_Nanoseconds, Idle_Nanoseconds, and Idle_Waits, and
        the runtime snapshot ABI moves to version 6. Idle time is clamped to uptime and
        both come from one clock reading, so callers can always take the difference or
        the ratio. tests/native/process_lifecycle_probe.c pins that ABI and its layout,
        and moves with it.

        The cost is measured rather than asserted. runtime_callback_bench adds
        poller_idle_cycle for the instrumented path and monotonic_clock_read for the
        unit of work it adds; benchmarks/idle_wait_rate reports the rate a loop
        actually reaches, because the effect is far below what a differential timing
        run resolves on this host. On macOS/AArch64 a reading costs about 20 ns, a
        socket ping-pong reaches roughly 32,000 to 38,000 waits per second per loop,
        and a loop doing nothing else reaches roughly 120,000 to 160,000: under 0.2%
        and under 0.7% of a loop's time respectively.

        Checks run: ./scripts/test.sh (pass, including the new
        observability_utilization_smoke), ./scripts/docs.sh (pass, no new warnings),
        ./scripts/bench-runtime.sh.

      9. 6c4bfc3c
        Problem: The guide cannot tell a reader whether a group is busy

        Step 10 of the guide lists the readings that diagnose a group, but every one of
        them describes queue contents. A reader who wants to know whether an event loop
        is saturated has no entry to follow, and the utilization fields the runtime now
        publishes appear only in README.md and the generated API reference.

        Solution: Document loop utilization where the guide diagnoses a group

        A new subsection explains what the runtime measures, why the subtraction is
        always valid, and the two readings that look alike: a group whose tasks all
        wait resembles a group with nothing to do, and a task that never suspends keeps
        its loop out of the poller and reports as fully busy. A decision row places the
        measure next to the queue-depth readings it qualifies. The cost paragraph names
        the measured figures and the script that reproduces them, rather than asserting
        that the accounting is cheap.

        The worked example is compiled and run by tests/guide_utilization_example.adb.
        The first draft of that example did not compile, because Counter is a modular
        subtype and the subtraction needs a use type clause the guide had not shown. A
        test main is the only check that keeps a printed example honest about the
        visibility a reader must supply.

        Checks run: ./scripts/test.sh (pass, including the new
        guide_utilization_example), ./scripts/build-site.sh, and check-site.mjs over
        the built site as CI runs it.

      10. fb881640
        Problem: The utilization copy states a rule that does not hold

        The website/AGENTS.md technical review is required for any changed capability,
        limit, or timing claim, and running it on the new guide section found four
        faults.

        Two are wrong rather than unclear. The guide told a reader that `Counter` needs
        a `use type` clause because the subtype is modular; the clause is needed
        because the operators of a type declared in another package are not directly
        visible, so the stated rule teaches the wrong thing. The guide also said an
        event loop waits in its poller only when no task can run, but the loop polls
        with a zero timeout while work is ready, and the same section counts that
        polling as busy time.

        The remaining two narrow a claim that had become broader than the code.
        "Dispatching, polling with work ready, or running task code" reads as an
        exhaustive account of a loop's busy time and omits timer promotion, file
        submission, and cancellation processing. That wording appeared in the guide,
        README.md, and the Group_Snapshot field documentation, so all three change
        together. `Group_Snapshot` and `Snapshot` appeared only inside the code block
        and were linked nowhere in prose, which the API-link rule does not allow.

        Solution: Correct the two faults and narrow the two broad claims

        The editorial and controlled-language passes contributed three further changes:
        one repeated paragraph opening, "idle fraction" used before the section
        introduces it, and "reading" carrying both a clock read and a snapshot.

        Checks run: ./scripts/docs.sh (pass, no new warnings),
        ./scripts/build-site.sh with check-site.mjs over the built site,
        and observability_utilization_smoke, guide_utilization_example, and
        observability_smoke rebuilt and re-run.

      11. bca8ad7f
        Problem: Previewing the built site needs an ad-hoc server command

        scripts/build-site.sh writes the complete site to build/site, but nothing
        records how to serve it. Reading a guide page as it will be published means
        inventing a static-server invocation each time, and picking a port that does
        not collide with a development server already running.

        Solution: Record a launch configuration that serves the built site

        The entry serves build/site on port 8231. It reads the build output and does
        not produce it, so run scripts/build-site.sh first and again after editing
        anything under website/.

        Checks run: served build/site through the entry and loaded the guide page.

      12. 104d406f
        Problem: macOS L1 detection reports efficiency-core capacity

        The macOS body queries the flat hw.l1dcachesize sysctl. On a heterogeneous
        Apple silicon host that name reports the efficiency-core capacity, not the
        performance-core capacity: one 12P/4E host reports 65536 bytes for the flat
        name against 131072 for hw.perflevel0.l1dcachesize. Flyology_Cachelines.
        L1_Data_Cache_Size therefore reports half the performance-core L1d capacity,
        and L1_Data_Cache_Slots derives its slot count from that halved value.

        The reader also assumed every queried name stores a 64-bit value. It read
        each name into one 64-bit object and accepted a short reply, so a 32-bit
        value was correct only because Darwin is little-endian and the object was
        zero-initialized. The per-level names are 32-bit.

        Solution: Prefer the highest performance level and read the reported width

        macOS 12 and later describe a host whose cores are not identical as ordered
        performance levels, where hw.perflevel0 is the highest-performing level. The
        macOS body now queries hw.perflevel0.l1dcachesize and falls back to the flat
        name only on a host that publishes no performance level, such as macOS 11 and
        earlier or an Intel Mac. Querying hw.nperflevels first would add nothing: the
        per-level name exists exactly when the host publishes performance levels.
        Hardware_Cache_Line_Size is unchanged, because Darwin publishes no per-level
        line size and both Apple silicon core types use the same line.

        The public API keeps its Cache_Query_Result surface. Reporting per-level
        geometry is a separate design question, and it should not ride along in a
        detection correctness fix.

        The sysctl reader moves into a new private Flyology_Cachelines.Macos child,
        mirroring the existing Flyology_Cachelines.Linux split between mechanism and
        policy. It requests each name's stored width before reading the value and
        rejects any other width, so a 32-bit name, a 64-bit name, a string, and an
        absent name are all handled without depending on byte order. Failed and
        malformed queries still degrade to Unavailable rather than raising.

        The GNATdoc comments on L1_Data_Cache_Size and L1_Data_Cache_Slots, the crate
        README, and the website cachelines guide now state that a host whose cores are
        not identical reports one core type, and which one each platform reports. A new
        macOS detection test mirrors the Linux one: it exercises the sysctl reader
        directly and checks that the reported capacity is the highest performance level
        the host publishes.

        Checks run: ./flyology_cachelines/scripts/test.sh (the native test now reports
        131072 bytes of L1 data cache on a 12P/4E host, and the new macOS detection
        test passes) and ./flyology_cachelines/scripts/docs.sh (zero GNATdoc warnings).

      13. d3af8647
        Problem: The Linux detection test requires an optional mechanism

        Flyology_Cachelines.Linux_Testing asserts that both Detect_From_Sysconf and
        Detect_From_Sysfs report a value. Only their composition is guaranteed:
        glibc answers _SC_LEVEL1_DCACHE_SIZE and _SC_LEVEL1_DCACHE_LINESIZE from
        CPUID on x86-64, but reports zero on aarch64, where sysfs is the only
        mechanism. Detect already treats sysconf as optional and falls back to
        sysfs, so the test is stricter than the code it covers.

        The test therefore fails on aarch64 Linux with "sysconf cache detection
        failed". CI runs ubuntu-latest on x86-64, where sysconf answers, so the
        failure is invisible there. It reproduces on aarch64 Linux, which AGENTS.md
        tells contributors to prefer on Apple silicon because it is native and
        faster.

        Solution: Require the composition and check each available result

        Run now requires that at least one mechanism reports a value, and checks
        consistency only for a mechanism that reported one. That is what the
        production detector promises: it composes sysconf and sysfs, and returns
        Unavailable only when neither answers.

        Checks run: the crate suite on aarch64 Linux in a container, where the
        detection test now passes, and on macOS, where it is not built.

      14. 04658ed7
        Problem: Linux cache detection describes only CPU 0

        Flyology_Cachelines.Linux reads one L1 data-cache geometry: sysconf answers
        for the calling CPU, and the sysfs fallback reads cpu0. A host whose cores
        are not identical has more than one geometry, and neither mechanism says
        which core the reported one belongs to, or that others exist.

        macOS already publishes ordered performance levels, so the macOS body can
        prefer the highest-performing one. Linux publishes per-CPU descriptions and
        no single ordering, so the equivalent information has to be derived before
        any public per-core-type query can work on both platforms.

        Solution: Group CPUs into core classes and record what ordered them

        Detect_Core_Classes enumerates the CPUs the host lists as present, reads
        each one's L1 data-cache geometry and capacity, groups CPUs reporting
        identical values into a class, and counts each class.

        Classes are grouped on capacity and geometry together. Grouping on geometry
        alone merges two core types that happen to share an L1 data-cache size,
        which real designs do.

        Ordering uses whichever key separates the classes, and Core_Classes reports
        which one did, so a caller can tell an authoritative order from an inferred
        one:

        - Host_Reported: the kernel's per-CPU capacity values separated them.
        Capacity is the scheduler's own measure of relative CPU performance and
        accounts for microarchitecture and clock. Architectures selecting the
        generic topology code publish it under cpuN/cpu_capacity.
        - Inferred: no capacity separated them, so they are ordered by descending
        L1 data-cache capacity. That holds on current hybrid parts and carries
        no meaning on a host whose classes differ some other way. x86-64 does
        not publish capacity, so its hybrid parts land here.
        - Unordered: fewer than two classes, or nothing separated them.

        Cores and CPUs are counted separately. SMT siblings share one L1 data cache,
        so the cache's sharing list identifies which CPU represents a physical core.
        Counting logical CPUs as cores overstates a 24-core host with two threads
        per core by a factor of two.

        Detection fails closed. A missing or malformed CPU list leaves only CPU 0 to
        enumerate, enumeration is bounded, a CPU whose description cannot be read is
        skipped, and a host reporting more classes than the table holds reports none
        rather than a table that silently omits a class.

        Detect_Core_Classes takes the CPU root as a parameter defaulted to the real
        sysfs path. Grouping, ordering, and the SMT distinction cannot be reached on
        a uniform test host, so the detection test drives them with committed
        fixture trees: two classes separated only by capacity, two classes separated
        only by geometry with the smaller listed first, SMT pairs sharing one cache,
        and a CPU list with a gap.

        Nothing calls Detect_Core_Classes outside the test yet. The public
        per-core-type query, and the elaboration cost of walking every CPU, belong
        to the change that adds that query.

        Checks run: the crate suite on aarch64 Linux in a container and on macOS.
        Detection was also replayed against captured CPU descriptions from a 48-CPU
        x86-64 host with two threads per core, which reports 24 cores against 48
        CPUs and no capacity, and from an 80-CPU aarch64 host, which reports 80
        cores against 80 CPUs and a published capacity.

      15. ba8438da
        Problem: Cache queries cannot name a core class

        Flyology_Cachelines reports one L1 data-cache capacity. A host that combines
        core types has one per type, so a single value silently describes whichever
        type the platform body happened to pick and gives a caller no way to ask
        about the others, or to learn that others exist.

        The two platforms also disagreed. macOS reported the highest performance
        level, while Linux reported whichever cache its own mechanism described:
        sysconf for the calling CPU, sysfs for cpu0. The same call therefore meant
        different things on the two platforms.

        Solution: Make the core class an explicit parameter of every cache query

        Core_Class names one class of cores that report a single cache geometry.
        Core_Class_Count reports how many the host distinguishes, Core_Class_Cores
        and Core_Class_CPUs describe each one, and L1_Data_Cache_Size and
        L1_Data_Cache_Slots take the class they describe. The parameter defaults to
        Fastest_Core_Class, so existing calls keep compiling and now mean the same
        thing on both platforms: the class the host ranks highest.

        Core_Class_Ordering reports what produced that rank, because it is a host
        fact on some platforms and the crate's inference on others. macOS performance
        levels and the Linux per-CPU capacity values are Host_Reported. A host
        publishing no rank is Inferred, ordered by descending L1 data-cache capacity.
        Fewer than two classes is Unordered.

        Cores and CPUs are reported separately. Sibling CPUs under simultaneous
        multithreading share one core's L1 data cache, so a 24-core host with two
        threads per core reports 24 cores and 48 CPUs in one class.

        Hardware_Cache_Line_Size takes no class. macOS publishes no per-class line
        size, and the core types of current heterogeneous parts share one line size,
        so a per-class query would have one answer to give.

        The host is now inspected on first use rather than during elaboration.
        Describing every class means reading one description per CPU on Linux, which
        measures 14 ms for 48 CPUs and 24 ms for 80. A program that links this crate
        and never asks about the host should not pay that at startup. The inspection
        is idempotent, so a race on the first query can duplicate work but cannot
        produce a value neither caller computed; the ready flag is atomic and is set
        after the result is stored.

        Flyology_Cachelines.Platform now answers one Detect call describing the whole
        host, and the root package body owns the single memoization. The two Linux
        bodies share one translation and differ only in what they report when sysfs
        describes nothing: the x86-64 body can still read the calling CPU through
        CPUID. Flyology_Cachelines.Linux drops its own class and ordering types in
        favour of the public ones, so the crate has one Core_Class.

        The website cachelines guide is corrected alongside the API. Adding the Class
        parameter changed the generated GNATdoc anchors for L1_Data_Cache_Size and
        L1_Data_Cache_Slots, so the guide's links to them became dangling fragments;
        both now point at the regenerated anchors. The guide also claimed detection
        happens during package elaboration, which is no longer true. The new entities
        are linked to their generated entries on first mention.

        Checks run: the crate suite on macOS, where a 12P/4E host reports two
        host-ordered classes of 131072 and 65536 bytes across 12 and 4 cores; on
        aarch64 Linux in a container; and on an x86-64 Linux host with 24 cores and
        two threads per core, which exercises the CPUID body and reports 49152 bytes
        across 24 cores and 48 CPUs. GNATdoc builds with no warnings.

      16. 9782c81b
        Problem: The shared L2 cache is not reported

        Flyology_Cachelines reports L1 but not L2, so a caller sizing a working set
        against the level it will actually spill into has nothing to read.

        The flat sysctl this crate would naturally have used is wrong in the same way
        hw.l1dcachesize was, and by a larger factor. On a 12P/4E Apple silicon host
        hw.l2cachesize reports 4194304, the efficiency cluster's cache, against the
        performance cluster's 16777216. Adding L2 before core classes existed would
        have reproduced the original defect at four times the size instead of two.

        Reporting a capacity alone would also mislead. L2 is rarely private: that same
        host shares 16 MiB across six performance cores and 4 MiB across four
        efficiency cores, so neither figure is a per-core budget.

        Solution: Report L2 capacity and how many cores share it, per class

        L2_Cache_Size and L2_Sharing_Cores take the same core class as the L1
        queries. A sharing count of one means the cache is private to a core; a
        larger count means the reported capacity is divided among that many cores.
        The GNATdoc on each function points at the other, because reading either
        alone invites the per-core mistake.

        macOS reads hw.perflevelN.l2cachesize and hw.perflevelN.cpusperl2. Linux
        reads the level 2 entry of each CPU's cache description, counting the CPUs
        its shared_cpu_list names. Both counts arrive as logical CPUs and become core
        counts through the class's own threads-per-core ratio, so a host with two
        threads per core does not report twice the cores sharing a cache.

        Parsing a CPU list needs more than its leading index, so the Linux body gains
        List_Count, which sums the single indexes and inclusive ranges a list names.
        Describing L2 costs no extra file reads: the level 2 entry is found in the
        same pass over the cache indexes that already locates the level 1 data entry.

        The website cachelines guide gains the same pairing, with both names linked
        to their generated entries.

        Checks run: the crate suite on all three supported targets. A 12P/4E macOS
        host reports 16777216 bytes across 6 cores for its performance class and
        4194304 across 4 for its efficiency class, and the macOS test asserts that
        these come from the performance level rather than the flat name. An aarch64
        Linux host reports 16777216 across 6 cores. An x86-64 Linux host with 24
        cores and two threads per core reports 2097152 across 1 core, where sysfs
        gives 2048K shared by CPUs "0,24"; that run also compiles the CPUID body,
        which builds nowhere else. Fixtures cover a per-class shared L2, an L2 shared
        across SMT siblings, and a private L2. GNATdoc builds with no warnings.

    4. 9782c81b updated to 7be049fcindex 6e2db0ef

      1 source commit

      1. 7be049fc
        Problem: A stalled package mirror hangs CI instead of failing it

        The two OpenSSL install steps in the test job carried no bound, so a mirror
        that stops answering leaves apt waiting rather than returning an error. On
        2026-08-19 run 32297071503, job 96211136305 sat on "Install OpenSSL 3 on
        Linux" for 32 minutes and had to be cancelled by hand; it was the only check
        blocking PR #49. Its log shows apt-get update fetching noble-security
        InRelease at 20:13:04 and producing no further output until cancellation. The
        macOS half of the same job passed, so nothing was wrong with the tests.

        Left alone the job would have run to GitHub's six-hour default. Nothing else
        in either workflow was bounded either: the checkout, the Alire install, the
        index configuration, the Java and TLA+ downloads, and the GNATdoc install all
        reach the network under the same default, and no job in this repository
        declared a timeout at all, unlike the sibling repositories.

        Solution: Bound every job and every step that reaches the network

        Each job now declares a timeout-minutes, and so does each step that fetches
        something. The bounds are generous multiples of what healthy runs measure
        over the last 60 successful runs of each workflow, so they can only fire on a
        stall. Jobs: test observes at most 17 minutes on macOS and 11 on Linux and is
        bounded at 60; proof observes 6 minutes and TLA+ 7, both bounded at 30; the
        pages build observes 69 seconds and is bounded at 20, its deploy 10 seconds
        and bounded at 15. Steps: everything network-touching is bounded at 10
        minutes against observed maxima of 1 to 6 seconds, except the Alire install,
        which downloads the toolchain, observes 100 seconds, and is bounded at 15.

        A step timeout alone would only have converted the 32-minute hang into a
        10-minute one, because the stall is inside a single apt-get update that never
        returns. That command is now capped per attempt with timeout(1) and retried
        twice with 15 and 30 second backoff, so one unresponsive mirror costs a
        retry rather than the job. The install that follows is capped as well but not
        retried: a package that cannot be resolved should fail on the first try. The
        worst case is three 120-second attempts plus a 10-second kill grace, 45
        seconds of backoff, and a 190-second install, which is 10m25s and lands
        inside the 12-minute step bound, so the annotation naming the transient
        mirror is what the log ends on rather than a bare cancellation.

        GNU timeout is used directly rather than scripts/run-with-timeout.sh. That
        helper exists for portability to macOS, and this step is Linux-only.

        The TLA+ download gains --connect-timeout 30 and --max-time 120 alongside its
        existing --retry 3, because curl retries a failed transfer but not a stalled
        one, and --max-time resets per attempt. Four bounded attempts stay inside the
        step's 10 minutes.

        Build, test, proof, and model-checking steps keep no step bound. Their
        duration is workload-dependent, a bound sized for them would be a performance
        budget rather than a stall detector, and the job timeout already covers them.
        Nothing about what is installed, or how anything is built or tested, changes.

        Checks run: both workflows parse. The retry script was extracted from the
        committed YAML and driven under bash -e against stub apt-get invocations for
        five outcomes: first-try success runs one update and one install; two
        failures then success runs three updates and installs; three failures exit 1
        with the annotation and never install; an install failure propagates its exit
        status without retrying; and exit 124, which is what timeout(1) reports when
        it kills a stalled command, is treated as retryable. The real commands were
        then run in an ubuntu:24.04 container on coreutils 9.4, the runner's version:
        the bounded update succeeds, interrupting one mid-flight reports 124, a
        retry after that kill still succeeds rather than inheriting a poisoned apt
        state, and the bounded install still yields OpenSSL 3.0.13 through pkg-config.

        The convention is recorded in AGENTS.md so it holds for new steps, and it
        matches the job-level timeouts already used in flyology-http and
        gnat-patches, whose install steps want the same treatment.

        Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

    5. 7be049fc updated to a53da35dindex b5569962

      1 source commit

      1. a53da35d
        Problem: The allocators dependency accepts any version

        The allocator crate is developed alongside the runtime in this repository and
        released on the same development line, but the dependency on it is declared as
        "*". Nothing stops a dependent from resolving an allocator release built for a
        different line, and the index has been carrying a tighter constraint by hand to
        compensate.

        Solution: Constrain allocators to its development line

        Declare the line the allocator crate actually publishes, so the constraint
        travels with the manifest instead of being reapplied wherever it is indexed.

        Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

    Compare source revisions
    Development update

    flyology_cachelines 0.1.1-dev

    5 updates: 91d6a0f6 through a53da35d

    Cache-line-aware storage and cache information for Ada

    Manifest fields
    origin
    Show all 5 updates
    1. 91d6a0f6 updated to 9a24bf68index 510cfcf6

      39 source commits

      1. 40849230
        Problem: DNS smoke depends on hosted-runner timing

        The functional loopback checks use retry intervals too narrow for occasional macOS hosted-runner stalls. An early client exception also waits behind cancellation coordination and loses the operation that failed, leaving only a generic lifecycle assertion.

        Solution: tolerate stalls and report DNS smoke stages

        Use functional smoke deadlines that accommodate runner scheduling, let coordination observe early client completion, and report the execution model and operation stage for unexpected exceptions. The dedicated DNS resilience smoke retains narrow deadline coverage.

      2. 347604c6
        Problem: Codex and Claude usage across the Flyology workspace is difficult to audit

        Session logs are distributed across project checkouts, worktrees, sister
        repositories, and nested agent sessions. Their token counters also contain
        cached input, repeated cumulative records, inherited history, and duplicated
        Claude message entries, making straightforward aggregation inaccurate.

        Solution: add a portable incremental AI usage audit

        Add a self-contained PEP 723 Python script that discovers the workspace from
        its containing repository and scans associated Codex and Claude Code logs,
        including worktrees, subagents, and workflows.

        Deduplicate cumulative and inherited records, categorize base input, cache
        reads and writes, output and reasoning tokens, and estimate API-style costs
        using model-specific pricing. Persist JSON cursors and daily aggregates so
        subsequent runs process only new log records.

        Provide summary, daily, weekly, provider, and model breakdowns with JSON
        output, date filtering, configurable paths and timezone, state rebuilding,
        and integrity diagnostics.

      3. 73925055
        Problem: Flyology website presents Runtime as the umbrella

        The landing page, navigation, guide index, and machine-readable documentation center Flyology Runtime while standalone libraries share the project identity without depending on it. Visitors cannot reliably distinguish the runtime core, runtime-dependent protocol libraries, and independently adoptable components, and several component documentation paths are missing or placed under the wrong section.

        Solution: Present Flyology as the project and Runtime as its core

        Reorganize the landing page around the project umbrella, add focused Runtime and Libraries pages, move Guide, Architecture, and the main API under Runtime, separate standalone documentation from the Runtime guide, link each published component Guide and API, fix the scrollable guide topic rail, and align README, product, design, journal, build assertions, and llms.txt with the same dependency model.

      4. 6cb6887f
        Problem: Flyology package discovery and maturity guidance compete

        The redesigned project pages repeat the experimental label in several nearby locations while the curated Libraries directory has no path to the complete package index. Readers see redundant maturity warnings but cannot easily reach version, dependency, availability, and compiler-build records for every published package.

        Solution: Clarify maturity guidance and link the complete crate index

        Keep experimental status in the primary explanatory context, make constraints and adoption guidance more direct, and link crates.flyology.org from the Libraries introduction, footer, and llms.txt documentation map.

      5. 4738d656
        Problem: The crate index is absent from shared site footers

        Only the Libraries page exposes the complete package catalogue in its footer. Readers arriving on Runtime, Guide, Architecture, Journal, or the project overview have no equivalent utility path to package versions, dependencies, and availability records.

        Solution: Add the crate index to every shared footer

        Place the Crate index utility link first in each hand-written footer, including the journal entry template, while retaining every page-specific navigation link.

      6. 5b7c3925
        Problem: Cancellation promptness is asserted as a per-round wall-clock bound

        Check_Parent_Cancellation_Is_Prompt in tests/task_scope_faults_smoke requires
        every one of 16 rounds to propagate parent cancellation within 5 ms.
        Propagation crosses two lightweight-task wakes, and a contended shared runner
        can deschedule either of them for milliseconds, so the check reports host
        scheduling as often as it reports the mechanism. CI run 32100324387 failed
        this assertion on its first attempt and passed on a rerun of the identical
        commit 71df9ed, whose only change is .github/workflows/pages.yml. Locally,
        96 spinning processes on 16 cores plus nice -n 20 reproduce the failure in
        2 of 30 runs, and 1280 rounds measured under that load put the median at
        78 us with 0.9 per cent of rounds past 5 ms: the mechanism is prompt and the
        bound is reporting the host. A bare pragma Assert also names only a source
        line, so a real regression is indistinguishable from a stalled round.

        Solution: Require most rounds to be prompt, bound the rest, and report them

        The check now measures all 16 rounds, requires at least 10 of them within
        1 ms, and requires no round past a 0.5 s sanity ceiling. That is a stronger
        claim about the mechanism rather than a weaker one. The retired 10 ms polling
        monitor spreads its latency across its period and places about 1.6 of 16
        rounds inside 1 ms, so it clears the new bar about once in two million runs
        against once in sixty-five thousand for the old whole-round 5 ms bound;
        reinstating that monitor put 0 of 16 rounds inside 1 ms and failed the new
        check on all five idle runs. Under the load that failed the old check in
        11 per cent of runs, the new check passed 60 of 60. A failing round set is
        printed to standard error so the next failure names the rounds and their
        latencies instead of only the assertion line.

      7. 857820c4
        Merge pull request #47 from flyology-ada/claude/gifted-sanderson-75002d

        Problem: Cancellation promptness is asserted as a per-round wall-clock bound

      8. 5dfa0d25
        Problem: Broken site links reach main before anything checks them

        The site check that validates local links and fragment targets runs only in
        the Pages workflow, which triggers on a push to main and on manual dispatch.
        No pull-request workflow builds the site, and ci.yml has no site job, so a
        change that breaks a link passes every check a reviewer sees, merges, and
        then fails the Pages build on main. The site stops publishing at the point
        where the mistake is hardest to attribute.

        The hand-written pages carry 457 links into generated GNATdoc entries across
        eleven guide and architecture pages. GNATdoc names each entry by a hash of
        the declaration, so changing a public subprogram's parameters gives it a new
        anchor and silently strands every hand-written link to it. Editing the
        surrounding documentation comment does not, which makes the failure easy to
        miss: prose edits are safe, and a signature change quietly is not.

        Solution: Build and check the site on pull requests

        The Pages workflow now also runs on pull_request. The build job is
        unchanged for a push, and on a pull request it builds the site and runs the
        same link check without touching Pages: configuring Pages, uploading the
        artifact, and the deploy job are all skipped. A pull request therefore needs
        no Pages permission, which also keeps the job usable from a fork.

        Concurrency now groups per ref. One group for every event serialized
        unrelated pull requests behind each other and behind a deploy. Pushes to main
        still share one group and are still never cancelled; a pull request cancels
        its own superseded runs.

        This adds a toolchain and GNATdoc build to each pull request, which is the
        cost of resolving generated anchors: the check can only confirm a fragment
        exists by generating the page that defines it.

        Checks run: the workflow parses, has no tabs, guards exactly the three
        Pages-specific steps, and keeps the link check unguarded. check-site.mjs was
        confirmed to catch this class of breakage against a page carrying one stale
        API fragment, where it reports "missing fragment target" and exits non-zero.
        This pull request triggers the new job, so its own run is the end-to-end
        check.

      9. 252f4fd7
        Problem: Ada programs cannot see the host's memory-node structure

        A machine with more than one processor package attaches memory to each of
        them, and memory attached to the package a thread runs on is reached faster
        than memory attached to another. Nothing in this repository reports that
        structure. Ada itself does not describe it either: System.Multiprocessors
        covers processors and dispatching, and the language has no notion of a
        memory node at all.

        Without it, a program that wants its work near its memory has nothing to
        place against.

        Solution: Adopt flyology_numa as a nested standalone crate that reports it

        The crate reads the host description and reports memory nodes, the
        processors attached to each, firmware-declared distances, per-node memory,
        and processor packages. It does not place memory; that is a separate
        question this crate does not answer.

        Three decisions shape the interface.

        Topology queries are total. A host with no memory-node structure reports one
        node holding every processor, because such a host genuinely has one memory
        domain. Support distinguishes a description that was read from the host from
        that single-domain description. Individual facts a host does not answer use
        the existing variant-record convention with Value_Or, so a caller names its
        own fallback rather than receiving a plausible number.

        Online and permitted nodes are reported separately. A container is shown the
        whole machine's node list while a control group restricts what it may
        allocate on, so the host description alone does not establish permission.
        Allowed_Nodes intersects the description with Mems_allowed_list from the
        process status file.

        Node and processor numbers are the host's own, and sparse. They match sysfs
        paths and numactl output, so a reported number is the number to look up
        elsewhere. To_CPU performs the Ada processor mapping GNAT applies unchecked,
        and declines when the host's numbering has a gap the mapping cannot carry.

        A description this crate cannot read is reported as a shortfall rather than
        guessed at. Support.Complete goes false when any part of the description was
        refused: a node or processor number beyond the represented range, a list
        naming more ranges than the reader holds, an unreadable processor list, or a
        permitted-node list the host named and the reader did not understand. The
        distinction that matters is between a node with no processor attached, which
        is an ordinary memory expander, and a node whose processor list could not be
        read, which is not known to have none. A description that names nodes but
        attaches no processor to any of them is refused outright, because every
        machine has a processor.

        The sysfs reader names the directories it reads instead of assuming them, so
        it is host-independent text processing that compiles and runs everywhere.
        This departs from flyology_cachelines, which keeps all Linux code under a
        Linux source directory and tests only the host it runs on. The interesting
        cases cannot be reached that way: a development machine has one node and a
        container on one is single-node too. Twelve recorded descriptions under
        tests/fixtures cover two packages of one node each, two packages each
        divided into two memory nodes, a node carrying memory with no processor
        attached, sparse node numbering, a control-group restriction, a gap in
        processor numbering, an older host naming only its ordinary memory, and five
        descriptions the reader must refuse or report as incomplete. All are
        exercised on macOS, which has none of them.

        Set algebra lives in its own unit rather than the root body because
        discovery runs during the root package's elaboration and cannot call back
        into the body it is elaborating. Each step of the discovery chain names the
        body it needs with pragma Elaborate, so the ordering does not rest on the
        binder inferring it. Elaborate_All would not serve: its closure reaches back
        through the platform spec to the root body itself.

        A processor list is bounded at one range per processor rather than at 64,
        because a host that enumerates processors round-robin across its nodes gives
        each node a list of single-processor ranges.

        Verified with ./flyology_numa/scripts/test.sh on macOS aarch64 from a clean
        tree: both the host suite and the fixture suite pass, and clean builds of
        the linux, macos, and unsupported platform bodies through the crate's
        host-selection scenario variable emit no warnings, style diagnostics, or
        errors.

      10. 376d2481
        Problem: Flyology_NUMA reports memory nodes but cannot use them

        The crate describes which memory nodes a host has and which processors are
        attached to each. A program that wants its work near its memory can read
        that and then do nothing with it: there is no way to ask that a region's
        pages be drawn from a chosen node.

        Solution: Add Flyology_NUMA.Placement over the kernel's memory-policy calls

        Placement is a separate package from the reporting one because the two fail
        differently. Reading a description always succeeds; acting on one often does
        not. Support reports which of three states applies before anything is
        attempted, and every operation reports its own outcome rather than raising.

        The third state is the one worth having. A host may have no placement
        interface, or it may have one this process is refused. A container sandbox
        commonly refuses these calls while the machine underneath has memory nodes
        that other processes are using, and reporting that as a host without the
        facility would be wrong. Denied is therefore distinct from Unsupported_Host.
        The two are told apart by what the host said about itself rather than by the
        error number alone, because a sandbox may answer a refused call by claiming
        the call does not exist: a host that described its own memory nodes has the
        calls that act on them, so a refusal from such a host is a denial.

        Support is settled on the first call that needs it rather than while the
        package elaborates. A sandbox that answers a refused call by ending the
        process would otherwise end any program that merely links this crate, even
        one that never places memory.

        Apply_To places a range, Apply_To_Thread places what the calling thread
        allocates from then on, Node_Of_Address reports where a page ended up, and
        Permitted_Nodes asks the host afresh rather than reusing what it said
        earlier. A range must begin on a page boundary because placement acts on
        whole pages; an unaligned range is refused before the host is asked.

        Three details of the kernel interface are easy to get wrong and silent when
        got wrong, so each is handled deliberately.

        The node-bit count is decremented by the kernel before the mask is read, so
        passing the number of bits meant would drop the highest node. Placement
        passes one more than that, which names every node this crate represents
        while still asking for only the eight bytes the mask has. Reading the
        permitted nodes is bounded differently again: the kernel refuses a count
        below the number of nodes the host could ever have, counting nodes that are
        merely possible rather than online, so that read uses a buffer covering the
        largest node count Linux can be built for.

        Two policies take no node set, and the kernel rejects either of them when
        one arrives. Passing the set a caller naturally has to hand would therefore
        fail, so the set is dropped before the host sees it and the interface's
        promise that it is ignored is kept.

        The preferred policy takes a single node, not a set. The interface documents
        that only the lowest-numbered node is preferred rather than implying the
        whole set contributes.

        No C library wraps these calls. Their manual pages document a separate
        library's wrappers, not the one every program already links, so they are
        reached through the generic system-call entry point. That entry point is
        variadic, which is one of the reasons this repository admits C, but GNAT's
        variadic convention reaches it correctly without a C file and keeps the
        crate free of one, as flyology_cachelines is.

        Call numbers differ per architecture, and not only in value: the x86-64
        table and the table newer architectures share disagree on the order of
        get_mempolicy and set_mempolicy. Calling by a number from the wrong table
        reaches a working but unrelated kernel service, which is worse than not
        calling at all, so each table is written out separately and an architecture
        whose numbers are not recorded disables placement rather than borrowing
        them.

        That failure is silent by nature, so the host suite has an invariant that
        exposes it: a host that described its own memory nodes has the calls that
        act on them, so reporting no way to place memory means the calls were not
        reached. Building for one architecture with another's table was checked to
        fail on exactly that assertion rather than passing quietly, and passing a
        node set with a policy that takes none was checked to fail before the set
        was dropped.

        Verified on macOS aarch64, x86-64 Linux, and AArch64 Linux. macOS reports
        Unsupported_Host and places nothing. Both Linux architectures report
        Supported and complete every operation: every policy applied to a range and
        to the calling thread, a written page reported on an online node, an
        unaligned range refused, and an empty node set refused for a policy that
        needs one. Builds of the macos, linux and unsupported platform bodies across
        x86-64, AArch64 and an architecture with no recorded table emit no warnings,
        style diagnostics, or errors.

      11. 41e2d423
        Problem: Naming a memory node for an object means placing it by hand

        Flyology_NUMA.Placement acts on an address range. Using it to put an object
        on a chosen node means obtaining page-aligned memory, placing it, carving
        objects out of it, and releasing it afterwards, all in the caller's code and
        all outside the language's own way of saying where memory comes from.

        Ada already has that way: the storage pool of an access type. Nothing here
        supplied one.

        Solution: Add Flyology_NUMA.Pools, a storage pool whose subpools are nodes

        An access type names the pool and each allocation names the node, so where
        an object lives is written at the point it is created rather than arranged
        around it:

        Item : constant Sample_Access := new (On_Node (Arena, Near)) Sample'(...);

        Subpools are the part of the language that fits this. A pool alone would fix
        the node when the access type was declared; a subpool is chosen per
        allocation, which is what naming a node needs to be.

        The pool obtains whole pages from the host rather than taking memory from
        the ordinary heap. Heap memory may begin partway into a page whose remainder
        belongs to something else, and placing that page would move memory this
        crate does not own. Pages are placed before any of them is handed out, since
        placing them afterwards would leave whatever had already been written where
        the host first put it.

        Memory is handed out by advancing through pages already obtained, and goes
        back to the host when a subpool is deallocated or the pool is finalized.
        Freeing a single object does nothing. That suits memory built up and
        discarded together, which is what a node-bound arena usually is, and the
        interface says so rather than implying a general allocator.

        Ownership of the pages is left to the runtime's own teardown rather than
        taken over. The runtime keeps the records it needs to finalize an object
        inside the very pages that object lives in, and a pool that gave its pages
        back first would take those records with them; a pool holding anything with
        finalization would then fail on the way out of its own scope. Deallocating
        one subpool likewise forgets it, because the runtime has already detached it
        by then and a pool that still believed it owned it could never serve that
        node again.

        Only the policies that name a node can be given to a pool. The two that name
        none place nothing on the node the subpool stands for, so a pool built on
        one would report memory placed there that never was.

        Placement_Reached separates a host that placed the memory from one that
        could not, and says which of the two it means: the host accepted the
        request. Under a bound policy that puts the pages on the node; under a
        preferred one the host stays free to draw from elsewhere. Allocation
        succeeds either way, on the reasoning that memory in the wrong place still
        runs while no memory does not.

        A pool is not task safe, and the interface says so. Two tasks allocating
        from one subpool at once can be handed the same address.

        Verified on macOS aarch64, x86-64 Linux, and AArch64 Linux, and inside
        guests built to have several memory nodes, which no machine to hand does.
        scripts/multinode-check.sh boots a two-node guest and a four-node guest
        whose distances are uneven and one of whose nodes carries memory with no
        processor attached, then runs the host suite inside them. It was run on
        both x86-64 and AArch64, each emulating its own architecture, so that the
        placement calls a guest makes are the ones its architecture's table names. Those runs are
        what exercise choosing between nodes at all: memory bound to each node in
        turn and confirmed held by that node, including the node with no processor;
        interleaving spread over every node rather than drawn from one; and a node
        shown further from another than from itself.

        The suite gained cases for the two failures described above, and each was
        confirmed to fail before the change and pass after. Builds of the macos,
        linux and unsupported platform bodies across x86-64, AArch64 and an
        architecture with no recorded placement table emit no warnings, style
        diagnostics, or errors.

      12. a416d8dc
        Problem: The flyology_numa test entry point is not executable

        ./scripts/test.sh runs each crate's own entry point by path, so the file
        has to carry the executable bit. flyology_numa/scripts/test.sh was recorded
        without it and the whole suite stopped there, reporting only that a command
        could not be run.

        Running the script as an argument to a shell, which is what a person does
        while writing one, works either way and hides this.

        Solution: Record the executable bit, as the other crates' entry points do

      13. 550bc612
        Problem: flyology_numa is absent from the site and the API reference

        The crate ships, and nothing outside its own directory says so. It has no
        guide page, no generated API reference, and no entry in the library ledger
        or the machine-readable index. A reader who finds the other standalone
        crates on the site does not find this one.

        Solution: Adopt the crate into the documentation and the site

        The crate now builds its own GNATdoc reference, and the root documentation
        run builds and asserts it alongside the other crates. Publishing it required
        documenting the pool primitives the runtime calls, which had no comments,
        and describing the pool's discriminants in prose: @field names a record
        component, and a discriminant of a private type is neither.

        The package renaming that shortened System.Storage_Pools.Subpools in the
        public part is now in the private part. GNATdoc reported the public renaming
        on every documentation run, and the full name appears twice in the visible
        declarations rather than in every generated page.

        The guide page follows the order a reader needs: add the crate, read the
        node structure, use the permitted nodes rather than the online ones, handle
        a host with one memory domain, place memory, allocate from a node, and read
        distances and packages for what they say rather than what they suggest.

        Every API link on that page was resolved through the generated search index
        rather than by reading the generated markup, which does not put an entity's
        name where a reader of the HTML would expect it.

        The library ledger keeps its alphabetical order, so the new entry is S05 and
        the two entries after it move up.

        Verified with ./scripts/docs.sh, which builds the reference with no
        undocumented-entity warnings, and ./scripts/build-site.sh followed by the
        site checker, which reports 144 HTML files and 201 total files. The crate's
        own suite still passes.

      14. ae1e3ddf
        Problem: The landing page does not list flyology_numa

        The project map in the hero names each standalone library, and the
        catalogue below it links each one. Both lists stop at the crates that
        existed before this one. A reader who arrives at the site and looks for what
        Flyology offers does not learn that the crate exists.

        Solution: Add the crate to the hero project map and the catalogue

        Both lists keep their alphabetical order, so the entry sits between IRI and
        SIMD. The catalogue entry links to the guide, as the entries for the other
        crates with a guide on this site do.

        Verified with ./scripts/build-site.sh and the site checker, and by fetching
        the built pages: the hero and catalogue both list the crate, and all 39
        internal links on its guide page resolve.

      15. aa8b12ed
        Problem: The numa guide explains how before it explains what

        The page opens with a short definition in a callout and then goes straight
        to adding the crate. A reader who does not already know what a memory node
        is learns the interface before the reason for it, and a reader who does know
        still gets no picture of the machine the crate describes.

        Solution: Open with a section that explains memory nodes and draws one

        The section states what changes when a machine has more than one processor
        package, draws a two-node machine with a local and a remote access, and says
        plainly when placement is worth doing at all: a program that fits in cache,
        or one that allocates little, does not gain from it. The callout it replaces
        said less.

        The diagram uses only the classes the figure context defines. An earlier
        draft used a class that context does not style, and SVG then fell back to a
        solid black fill. That reads as deliberate against a dark background and
        wrong against a light one, which is how it survived a first look.

        Both themes were checked by computed style rather than by eye. The
        containers take the page's own surface and border colours, so they follow
        the theme instead of fighting it.

        Verified with ./scripts/build-site.sh and the site checker.

      16. 7b70cbf6
        Problem: Allocation algorithms are coupled to Flyology shared-memory policy

        Buddy, best-fit, and TLSF live inside the main package hierarchy, so bare-board runtimes cannot reuse them without also accepting Flyology identity, mapping, and shared-memory concerns.

        Solution: Extract allocation algorithms into a standalone crate

        Add flyology_allocators 0.1.0-dev with caller-owned regions, timed contention retries, native and ARM bare-board verification, and optimized memory primitives. Keep magic and schema policy in a thin Flyology adapter, pin the new crate from Flyology, and update integration tests and documentation.

      17. 7bf86246
        Problem: Standalone allocator performance has no focused comparison

        The extracted algorithms lack a reproducible benchmark against the platform allocator, making hot-path regressions and algorithm tradeoffs difficult to measure.

        Solution: Add a dedicated flyology_bench allocator shootout

        Add an optional hosted benchmark subcrate with fixed-size and fragmented-churn workloads comparing malloc, Buddy, Best-Fit, and TLSF in balanced paired rounds. Keep benchmark dependencies outside the bare-board crate closure and document release and smoke workflows.

      18. be44ac54
        Problem: Buddy allocator repeats checked address work on every node

        Profiling shows recursive Buddy allocation and release spend most of their time rebuilding and validating structure-relative node addresses. Release also validates each handle twice before its first mutation, making small allocation cycles substantially slower than the other standalone algorithms.

        Solution: Cache the validated Buddy node-table binding

        Retain the process-local node-table base in the attached view after validating its complete native range, use bounded node-relative addressing on hot paths, clear the binding on detach, and remove the redundant release validation while preserving validation before mutation.

      19. 283d5e71
        Problem: TLSF repeats checked address work on every metadata field

        Profiles of fixed allocation cycles show TLSF spending most of its time in free-list insertion and removal, block initialization, and handle validation. Each logical operation repeatedly recomputes and validates the same block base before touching adjacent scalar fields, leaving the constant-time algorithm dominated by address machinery.

        Solution: Reuse validated block bases across TLSF hot paths

        Validate each referenced block extent once, carry its process-local base through list mutation, splitting, coalescing, and handle release, and keep stored link, size, generation, state, and bitmap checks intact. Avoid a redundant ready-state check while the arena guard is held and replace size-class division by its exact power-of-two shift.

      20. e9199d66
        Problem: Best-fit allocator repeats metadata work on hot paths

        Profiling shows fixed-layout address validation, duplicate split and coalesce writes, and repeated AVL balance reads dominate Best-Fit allocation and release. This leaves both fixed cycles and fragmented churn substantially slower than necessary.

        Solution: Streamline checked Best-Fit metadata operations

        Cache the last complete block-header location in the local view, use a fixed-field address path that retains attachment and complete-header bounds checks, avoid tree metadata writes that insertion immediately replaces, and compute AVL balance inputs once per ancestor. The stored layout, persisted validation, guard behavior, handle generations, and bare-board dependency boundary remain unchanged.

      21. 05d2eb83
        Problem: Allocator benchmarks leave imported algorithms unoptimized

        The benchmark project selects release switches only for its own sources. Imported flyology_allocators units are compiled without optimization, making comparisons against the optimized system malloc misleading and overstating allocator hot-path costs.

        Solution: Force a clean optimized benchmark closure

        Build the benchmark and all imported Ada sources through gprbuild with explicit O3, debug symbols, Ada 2022, warnings, and validity checks. Document why the runner must apply switches across project boundaries.

      22. 77e1d163
        Problem: Benchmark arrays use obsolete aggregate syntax

        GNAT reports parenthesized array aggregates as obsolescent when the benchmark closure is compiled as Ada 2022, obscuring useful build diagnostics.

        Solution: Adopt Ada 2022 bracketed array aggregates

        Convert Flyology Bench array initializers and expressions to bracket syntax while retaining parentheses for record aggregates. Keep the obsolescent warning category enabled so future occurrences remain visible.

      23. 77ce4c04
        Problem: TLSF eagerly coalesces every released block

        Release repeatedly discovers physical neighbors and removes and reinserts free-list entries even when the next allocation can reuse the same size class. This makes steady fixed-size and churn workloads pay fragmentation-recovery costs on every operation.

        Solution: Defer TLSF coalescing until allocation requires it

        Return released blocks directly to their size class and perform a bounded, checked physical coalescing pass only after a normal TLSF search misses or before destroying an empty arena. Preserve boundary tags and bitmap/list validation, and cover adjacent runs, allocated gaps, attachment, stale handles, and complete teardown with adversarial tests.

      24. 562bdd61
        Problem: TLSF still advertises eager constant-bound behavior

        Lazy coalescing makes worst-case allocation linear and no longer joins neighbors during release, but both capability records and package comments retain the eager algorithm contract. Flyology also reuses the eager persisted identity even though version 2 readers reject valid adjacent free blocks produced by the new implementation.

        Solution: Publish the lazy TLSF contract and identity

        Report the linear worst-case search and deferred release coalescing in standalone and Flyology packages, document the miss-triggered pass, and advance Flyology TLSF to version/schema 3 so cross-version attachment fails at the immutable header. Add standalone capability coverage and a Flyology regression that rejects the complete eager identity.

      25. 288b03a2
        Problem: Best-fit repeats split and merge work on exact reuse

        Profiling shows fixed-size allocation cycles spend most of their Best-Fit time splitting a large free block during allocation and immediately removing and coalescing its remainder during release. Fragmented churn repeats related AVL maintenance even when the same physical block can be reused directly.

        Solution: Defer Best-Fit coalescing until allocation needs it

        Index released blocks directly for exact-size reuse. Before reporting exhaustion, validate the complete physical chain, coalesce every adjacent free run, repair boundary links, and retry the AVL search. Accept the resulting persisted representation on attachment, canonicalize empty arenas during destruction, report the resulting linear worst-case search capability, and cover adjacent frees, alternating gaps, stale handles, attachment validation, and teardown.

      26. 41578832
        Problem: Flyology Best-Fit identity permits incompatible lazy images

        Deferred coalescing leaves adjacent free blocks as a valid persisted Best-Fit state. The earlier eager reader rejects that state, but Flyology still advertises the same outer version and schema, so compatibility fails only after entering nested allocator validation.

        Solution: Version the Flyology Best-Fit lazy invariant

        Advance the Flyology-only adapter version and schema while retaining its magic. This makes older readers reject lazy images at the outer identity boundary and keeps standalone allocator metadata free of application identity.

      27. ec813587
        Problem: Best-Fit identity transition lacks Flyology coverage

        The lazy Best-Fit adapter advances its persisted version and schema, but the Flyology data-structure smoke test neither proves rejection of the eager version-2 identity nor reflects the linear fallback and deferred-coalescing capabilities.

        Solution: Exercise the Best-Fit version-3 boundary

        Temporarily replace a live Best-Fit arena outer identity with the version-2 values and require attachment to fail closed, then restore the image. Assert the truthful lazy-coalescing capabilities for both Best-Fit and TLSF.

      28. e1315591
        Problem: Buddy eagerly rebuilds the same free hierarchy

        Small allocation cycles repeatedly collapse a released leaf to the root and split the same path on the next allocation. Profiling shows those release stores and recursive rebuilding dominate Buddy's fixed-size cost.

        Solution: Coalesce Buddy trees only when allocation needs it

        Keep released nodes in the retained split tree, compact free subtrees before a search reports genuine exhaustion, and compact before empty-arena destruction. Add adversarial coverage for half-tree and root reconstruction plus stale handles, and expose the lazy-coalescing capability accurately.

      29. 4ad89a24
        Problem: Lazy Buddy reuse still traverses the retained tree

        After deferring coalescing, profiling shows fixed-size Buddy allocation is dominated by walking the same split path. Fragmented churn also revisits released orders even though the releasing view already knows a suitable free node.

        Solution: Cache one validated free node per Buddy order

        Keep process-local node hints in each attached view, validate persisted state before every hinted reuse, and discard all hints during coalescing and detach. Preserve the persisted layout and fall back to the complete tree for stale or missing hints; cover stale hints across independently attached views.

      30. 22998f64
        Problem: Lazy Buddy metadata boundaries are incomplete

        Buddy still advertises logarithmic eager-coalescing behavior, an eager Flyology reader can attach a retained all-free split tree and falsely report exhaustion for a parent-sized request, and Destroy may release its guard after a partially failed coalescing pass without poisoning the image.

        Solution: Harden lazy Buddy capabilities and lifecycle handling

        Advertise linear miss search and deferred coalescing, advance only Flyology's outer Buddy identity to version 3, and verify the retained two-leaf compatibility case. Check that an arena is empty before Destroy mutates it and poison any coalescing failure. Compile the standalone project as Ada 2022 for bracket aggregates and extend standalone and Flyology compatibility tests.

      31. 66888189
        Problem: Allocator guides still describe eager coalescing

        Buddy, Best-Fit, and TLSF now defer coalescing until an allocation miss, but the root, standalone, and website guides still advertise their former fast-path and worst-case behavior. The stale prose also describes a process-shared guard even though the standalone algorithms are usable with arbitrary caller-owned storage.

        Solution: Document lazy coalescing and view-scoped state

        Describe each successful lookup and miss-triggered coalescing path, report the resulting linear worst-case bound, and use attached-view terminology. Record that stored geometry remains stable while the valid state contract changes and Flyology adapters use version-3 identities.

      32. 94cd5b57
        Problem: Lazy allocator correctness lacks an executable model

        Buddy, Best-Fit, and TLSF now retain free structure on release and coalesce on allocation misses. Behavioral tests cover examples, but no bounded state-machine review checks shared guard ownership, block partitions, index publication, stale view hints, generation-stamped release, false exhaustion, or operation completion across interleavings.

        Solution: Model guarded allocator transitions in TLA+

        Add a parameterized extraction for the three algorithms with policy-specific splitting and selection, TLSF bin and bitmap state, Buddy view-local hints, lazy coalescing, retry, generations, and fairness. Add safe TLC configurations plus required false-exhaustion, stale-hint, stale-bitmap, stale-release, and nontermination counterexamples, wire them into the authoritative runner, and document the production mapping and abstraction limits.

      33. 4dc3e5c0
        Problem: Allocator models can drift from Ada transitions

        The bounded Buddy, Best-Fit, and TLSF models establish safety and liveness for their extraction, but review alone does not detect when persisted metadata, view-local hints, generations, handles, or size-class computations diverge from the standalone kernels.

        Solution: Compare canonical Ada and TLC allocator traces

        Add test-only private-state observers and bounded public-operation traces for all three kernels. Model the same traces in TLA+, compare every operation-boundary snapshot byte-for-byte in the authoritative runner, require no-retry liveness counterexamples, and run the conformance boundary in CI while retaining standalone ARM cross-build isolation.

      34. 54d77f0f
        Problem: allocators lack a slab and span policy

        Solution: add a standalone bitmap-slab and contiguous-span allocator, bridge it into Flyology, benchmark it against the existing policies and malloc, and cover its bounded state machine with positive and deliberately broken TLA+ configurations.

      35. 239aa004
        Problem: slab slot reuse lacks a publication edge

        Solution: publish the affected 32-bit bitmap word with release ordering and acquire it before validating the slot generation. Add bounded safe and deliberately broken TLA+ visibility models so TLC reproduces the former stale-handle acceptance.

      36. 195b83bf
        Problem: large span validation trusts the head extent

        Solution: add a corruption test that makes one large-span head claim its neighboring live allocation, then validate every head and tail descriptor field before reporting capacity or allowing release to mutate the claimed extent.

      37. 7a7bc16f
        Problem: The site does not list flyology_allocators

        The hero project map, the standalone catalogue, the library ledger, and
        llms.txt each name every standalone crate. This branch adds a new one, and
        all four lists stop at the crates that existed when the branch was written.
        A reader who arrives at the site and looks for what Flyology offers does not
        learn that the crate exists.

        Solution: Add the crate to the hero map, catalogue, ledger, and llms.txt

        Every list keeps its alphabetical order, so the entry sits first among the
        standalone crates and the ledger indices shift from S01..S07 to S02..S08.

        The crate publishes neither a guide page on this site nor a generated API,
        because scripts/docs.sh does not build one and flyology.gpr excludes the
        crate from documentation. The entries therefore link to the source tree
        only, as the Flyology QUIC entry already does for the same reason. Adding an
        api/flyology_allocators/ link would fail the site checker.

        Verified with ./scripts/build-site.sh and the site checker, which passes on
        141 HTML files, and by grepping the built pages: the hero, catalogue,
        ledger, and llms.txt all name the crate.

      38. 7dc419f2
        Problem: The data-structures guide links to pages GNATdoc no longer emits

        This branch turns Allocation_Algorithms.Buddy, Best_Fit, and TLSF from
        documented packages into generic instantiations of Allocation_Algorithms
        .Contract. GNATdoc emits no unit page and no declaration anchor for an
        instantiation, so the three API links the guide carries for them now resolve
        to nothing. main gained a site link checker after this branch was written,
        so the Pages workflow reports all three and fails.

        Solution: Present the three instantiations as code rather than links

        AGENTS.md asks that the first explanatory mention of a public entity link to
        its verified generated GNATdoc unit or declaration entry. No entry is
        generated for these three, so there is nothing to link, and pointing them at
        the kernels or at Contract would name a different entity than the prose
        does. The surrounding Arenas, Contract, Allocation_Capabilities, and View
        links are unaffected and still resolve.

        Verified with ./scripts/build-site.sh and the site checker, which now passes
        on 141 HTML files and 198 total files with zero problems.

      39. 9a24bf68
        Problem: The data-structures guide omits the slab/span allocator

        This branch adds Allocation_Algorithms.Slab_Span as a fourth arena allocator
        and says so in the README, but the guide section that tells a reader how to
        choose one still presents three. It names three adapters, describes three
        policies, gives three decision rows, and twice states that all three share
        one metadata guard. A reader choosing an allocator from this page does not
        learn the fourth exists, and the two counts now contradict the README.

        Solution: Describe slab/span alongside the other three and correct the counts

        The introductory paragraph names the adapter and states its shape: bitmap
        slots in fixed runs for small requests, contiguous runs for larger ones, with
        descriptors and generation tables outside the managed bytes. A decision row
        gives the selection rule and the reclamation behavior a caller can observe:
        requests up to half the configured run size take a generation-stamped slot,
        larger requests reserve whole runs, release keeps an emptied slab indexed for
        reuse, and a miss reclaims empty slabs to obtain the run or span it needs.

        The row also states that the run size is an allocator quantum rather than an
        operating-system page, because the name invites the opposite assumption.

        The half-run threshold matches the kernel, which sends a request to a slab
        class when Requested <= Run_Size / 2 and to a span otherwise. Both "all
        three" counts become four. The adapter is a generic instantiation, so like
        Buddy, Best_Fit, and TLSF it has no generated GNATdoc entry to link.

        Verified with ./scripts/build-site.sh and the site checker, which passes on
        141 HTML files and 198 total files, and by parsing the built page: tags
        balance and the new row renders between TLSF and the compile-time choice.

    2. 9a24bf68 updated to 60de2c69index 8a8e9de5

      1 source commit

      1. 60de2c69
        Problem: A development pin ships in the published manifest

        flyology.gpr imports flyology_allocators.gpr, and the manifest both declares
        flyology_allocators as a dependency and pins it to the in-repo directory.
        Alire honours pins only in a root crate's manifest, so a consumer resolving
        flyology from the index never receives that dependency. Its solution omits
        flyology_allocators entirely and gprbuild then fails with "imported project
        file flyology_allocators.gpr not found". A crate whose only dependency is
        flyology = "~0.1.1-dev" reproduces it in two lines.

        Nothing in this repository reports the fault, because the pin satisfies the
        dependency for every build performed here. The pin also hid two further
        assumptions that only the in-repo directory could satisfy.

        Solution: Resolve the allocators dependency from the index

        Drop the pin so the declared dependency resolves the same way for this crate
        and for its consumers. The published flyology_allocators 0.1.0-dev is built
        from this repository at the same commit and the same subdirectory, so the
        source reached is identical; only the path by which it is reached changes.

        Configure the organization index in this repository's own workflows. They
        carried the community index alone, because the pin meant no job here ever
        resolved flyology_allocators from an index, and it is published only in the
        organization index. Without that step alr reports an incomplete solution
        naming flyology_allocators as missing.

        Name the excluded documentation project through the imported project rather
        than through a repository path. Documentation.Excluded_Project_Files listed
        flyology_allocators/flyology_allocators.gpr, which resolved only while the
        crate sat in this working tree; as a dependency its project lives in the
        Alire build tree under a content hash. Flyology_Allocators'Project_Dir asks
        the imported project where it is, so the exclusion holds wherever the
        dependency is deployed and the allocator packages stay out of this crate's
        generated API, where they would otherwise be documented twice.

        Record the rule that produced the fault in the agent guide: no committed
        pins in a crate manifest, alr pin in the consuming workspace for unpublished
        work, and a declared dependency must resolve from the index. Name the
        gprbuild error there too, since that is where the fault appears and it names
        a project file rather than a crate.

    3. 60de2c69 updated to 9782c81bindex 75a836be

      16 source commits

      1. aeb10612
        Problem: The site does not list Flyology RDF

        The hero project map, the standalone catalogue, the library ledger, and
        llms.txt each name every component. Flyology RDF publishes a website, a
        guide, and three generated API references at rdf.flyology.org, but the name
        appears nowhere in this repository. A reader who arrives at the site and
        looks for what Flyology offers does not learn that the project exists.

        Solution: Add the project to the hero map, catalogue, ledger, and llms.txt

        flyology_rdf depends on flyology_iri only. It needs no runtime preparation
        and starts no tasks, so it belongs with the standalone libraries. Every list
        keeps its alphabetical order, so the entry sits between Flyology NUMA and
        Flyology SIMD and the ledger indices shift from S07..S08 to S08..S09.

        The ledger and llms.txt entries carry all three generated references, as the
        Flyology Postgres entries already do, because the project site treats the
        Notation3 and SPARQL APIs as first-class navigation.

        The llms.txt project-structure summary also omitted Flyology Allocators and
        Flyology NUMA, which the same file already listed further down. Both names
        join the summary here.

        Verified with the website-kit site checker, whose output is unchanged from
        the pre-change baseline, and by rendering the pages: the hero, catalogue,
        and ledger all name the project. The six linked URLs return 200.

      2. 2188ee0d
        Problem: The project map announces its framing and then hides the components

        The figure caption claimed "One project, two adoption paths" above two cards
        that already carry the same fact in their labels, so the caption restated
        what the diagram shows. The two card subtitles were not parallel either:
        "Core component" named a role while "No runtime dependency" named a
        dependency, so neither pair member helped a reader compare the paths.

        The component names below them were plain list items. A reader who found the
        name that matched the problem had no way to reach the component from the
        diagram and had to scroll to the catalogue to find the same name again.

        Solution: Drop the caption, make the subtitles parallel, and link the names

        The subtitles now read "Prepare the runtime" and "Add a crate", which state
        the two adoption paths as the actions they are. The figure keeps an
        accessible name through aria-label, and the figcaption rule leaves the
        stylesheet with the element it styled.

        Each component name becomes a link to its best available destination, which
        is the destination the catalogue below already uses: the project site where
        one exists, then the guide, then the generated API, then the source tree.
        The pill moves from the list item to the anchor so the whole badge is the
        hit target. Links open in a new tab and carry no underline, as requested, so
        hover brightens the border and adds a faint fill instead. Each list states
        the new-tab behavior once in its aria-label rather than repeating it in
        twelve hidden spans.

        Verified by rendering the page: every badge computes text-decoration-line
        none and cursor pointer, and the hovered badge is distinguishable from its
        neighbors. The site checker reports one new line against the baseline,
        api/flyology_debug/ from the new Debug badge, which resolves once
        scripts/docs.sh generates the GNATdoc output that this partial build omits.

      3. 5dfd5d36
        Problem: Nothing coordinates tools that need exclusive CPU capacity

        Two measurement runs that share a machine produce two wrong answers, and
        neither run can tell that it happened. The problem is not confined to
        benchmarks: a load generator, a soak test, or a profiler makes the machine
        loud, and a benchmark needs it quiet. Both want the same thing from opposite
        directions, and nothing lets them find each other.

        Worse, two runs that each suspend collection when they detect interference
        are symmetric controllers observing each other. Each pauses because the other
        is loading the machine, both then observe quiet, both resume together, and
        both immediately pause again.

        Solution: Specify a host CPU lock convention and implement it

        The convention is named for the resource rather than for benchmarking, so
        that the tools which create load take the same claim as the tools which need
        its absence. Conflict detection is flock and nothing else: liveness is the
        lock itself, so a holder that dies releases with no cleanup path, no stale
        registry entries, and no pid-reuse hazard.

        A machine-wide claim takes LOCK_EX on the claim file; a claim on individual
        CPUs takes LOCK_SH there and LOCK_EX on one file per CPU. Disjoint core-scoped
        claims therefore proceed concurrently while a machine-wide claim excludes them
        all, with no registry and no arbiter. Per-CPU claims are acquired in ascending
        order, because a total order is what stops two callers with overlapping sets
        from deadlocking on each other's partial claims.

        The path is a single deterministic default rather than a writability-probing
        fallback chain. A chain reintroduces the failure it was meant to prevent:
        /run/lock is 1777 on Debian and root-owned 0755 on Red Hat derivatives, so a
        root process and an unprivileged process on one machine would probe
        differently, land on different files, and each conclude it holds the machine.
        $TMPDIR is avoided for the same reason, being per-user on macOS.

        File content is diagnostic and is never consulted to decide conflicts. It is
        still specified and parseable, one key=value pair per line, because a reader
        must be able to name the holder; cwd is included because tool and pid alone do
        not distinguish one checkout or CI workspace from another. Readers open the
        file without locking, since a shared lock would block behind the very holder
        they are trying to identify, and must tolerate content that is empty, stale,
        or half-written.

        A claim is not proof of exclusivity, and the implementation does not present
        it as one. systemd PrivateTmp= bind-mounts a per-service directory over /tmp,
        so two services share every CPU and cannot see each other's claim files; that
        case is detected from /proc/self/mountinfo and reported as namespace-scoped.
        Separate containers are not detectable from inside and need an explicit shared
        path. A path can be proven private but never proven machine-wide.

        Only the C macros live in the native unit. GNAT's C_Variadic_2 convention
        calls open() correctly even on Darwin/AArch64, where variadic arguments are
        passed differently from fixed ones, so the protocol, the file grammar, and the
        /proc reader are all Ada. The convention compiles on every GNAT this crate
        supports, checked against 13.2.2 through 16.1.0 against an alire.toml floor of
        13, so no compatibility shim is carried.

        Verified by building the crate, and by taking claims on disk: the file matches
        the published grammar, parses with awk -F=, is created 0666, and per-CPU files
        are named beside the machine file.

      4. 13b71a5b
        Problem: The CPU gate only proves the host was quiet before warmup

        CPU_Quiescence samples host counters once, before clock characterization, and
        then never looks again. A machine that goes busy halfway through collection
        produces a result that reads as clean, and nothing in the measurement, the
        console card, or the machine-readable output says otherwise. The gate's own
        documentation admits it "cannot prevent new load from arriving after
        collection begins", and until now that was the end of the story.

        The obvious repair is not available either. Host utilization cannot simply be
        compared against a limit during collection the way the preflight does it,
        because by then the benchmark thread saturates a core and every sample would
        trip the limit.

        Solution: Watch for foreign load during collection and say what was found

        Foreign load is host busy time minus this process's own CPU time, so load the
        benchmark itself creates is correctly not foreign. The estimate scales the
        host busy ratio by wall time rather than converting ticks, so the platform
        tick length never enters the arithmetic. Cross-checked against top on a loaded
        machine, the two agree to within 0.1 percent.

        Three responses form a ladder. Observe records and keeps everything. Retake
        discards the contaminated window and collects it again. Pause waits for the
        host to settle, re-warms, and then collects it again. The re-warm is not
        politeness: a resumed run has cold caches, predictors, and frequency state, so
        without it the first sample after a pause is the outlier the pause existed to
        avoid.

        Nothing adjusts a reported statistic. A skew factor derived from observed load
        would be invented data, because the cost of interference depends on whether
        the contention is an SMT sibling, a shared cache, memory bandwidth, or another
        socket, and the same foreign share can mean no slowdown or a large one. Runs
        are annotated or repaired, never corrected.

        Observation happens between timed samples over windows of whole collection
        units, where a unit is one sample, one comparison pair, or one balanced
        multi-way round. A response therefore never splits the two halves of a pair
        and never lands mid-round, where it would spread interference unevenly across
        the cases a round exists to compare fairly. Windows carry a margin over the
        configured minimum: sized to only just reach it, ordinary batch jitter drops
        them below it and they silently degrade to observation. Host counters are
        tick-based, so a window that still falls short is recorded but never acted on.

        Discarding a window rolls back what the window changed. Per-sample values are
        written by index and survive a retake intact, but the position tally of a
        comparison pair and the process-telemetry summaries are running sums, so a
        discarded pass gives them back. Without that, a run with eighteen retained
        samples and twenty-four retakes would report elapsed time and an average CPU
        share covering forty-two samples, most of which were thrown away.

        Budgets degrade rather than abort. An exhausted retake or pause budget
        continues under Observe and reports it, and paused time is excluded from
        Maximum_Sampling_Time because waiting for the host is not collection.

        Placement is optional and sharpens attribution: with a strict binding every
        other CPU's busy time is foreign outright, and the placed CPU's share is its
        busy time minus the placed thread's own. SMT siblings join the watched set,
        because a process saturating the sibling of the placed CPU slows the
        measurement while leaving the placed CPU's own share clean, which makes
        sibling-blind core-scoped observation worse than host-wide observation rather
        than better. Placement is Linux-only in practice; Apple Silicon implements no
        thread affinity and rejects every request, so the Host_Control documentation
        no longer describes Darwin placement as merely advisory.

        Placement binds only the calling thread, so another thread of this process can
        occupy a watched CPU, where its time is indistinguishable from foreign load.
        Each window therefore reads process CPU as well as thread CPU, and their
        difference bounds how much of the watched capacity those threads could account
        for. Once that bound exceeds the configured foreign limit, the core-scoped
        answer can no longer address the question the limit asks: the run drops to
        host-wide observation, which is well defined for a multi-threaded process, and
        reports Attribution_Diluted. Otherwise a scheduler benchmark run under
        placement would spend its retake budget discarding samples over load it
        created itself. The window that reveals the dilution is discarded rather than
        recorded, because its value was computed under the attribution being
        abandoned.

        The direction of that fallback is deliberate. Core-scoped attribution
        subtracts only the placed thread, which over-reports interference when other
        threads share the watched CPUs; subtracting the whole process instead would
        deduct time our threads spent on CPUs outside the watched set, under-report
        foreign load, and let contaminated data pass as clean. Over-reporting shows up
        in the retake and contamination counts; under-reporting shows up nowhere.

        The host CPU claim is taken before the preflight gate, since waiting for a
        quiet host and then blocking on the claim leaves the quiet verdict stale.

        Everything observed reaches the console card, the CSV schema, and the JSON
        object. That visibility is the point: a run that had to repair itself must say
        so, or a heavily repaired result reads as a quieter machine than the one it
        ran on.

        Verified with ./scripts/test.sh on Darwin/aarch64 and in an Ubuntu 24.04
        container on Linux/aarch64, and under qemu-system-aarch64 across four CPU
        topologies. Core-scoped attribution asserts that it closed an observation
        window, so the thread-CPU probe it depends on cannot fail silently. Two
        assertions were checked against builds that defeat them: one with sibling
        collection disabled fails the sibling assertion under cores=2,threads=2 and
        passes without SMT, and one with the dilution check disabled fails the
        fallback assertion while a task of the test's own process burns CPU. Retake
        and pause are driven by a spawned process, because load raised inside this
        process is its own CPU time and is subtracted by design.

      5. 845bdaca
        Problem: The new guide section ignores the site's writing rules

        website/AGENTS.md governs hand-written pages under guide/**. The interference
        section met none of its API-link requirements and several of its style rules.

        Every public entity it introduced went unlinked: Interference, Placement,
        Host_Lock, the three Interference_Response literals, Maximum_Retakes, Window,
        Rewarm_Time, Maximum_Foreign_CPU_Percent, Include_Siblings, Require_Strict,
        Attribution_Diluted, and Environment. The same page already links
        CPU_Quiescence, Stable_Time, and Timeout, so the new section also read
        inconsistently against its own neighbours.

        Solution: Link the API entities and apply the three prescribed reviews

        The three reviews ran in sequence and are labelled here, since separate review
        agents were unavailable.

        Technical. "Foreign load is host busy time minus this process's own CPU time"
        held only without placement, because core-scoped attribution subtracts the
        placed thread rather than the whole process; the sentence now says so, and the
        placement paragraph states which CPUs the harness measures. "The re-warm is
        required" overstated a configurable field, so the text names Rewarm_Time and
        says what a zero value leaves behind. "When the difference exceeds the
        configured limit" named neither the limit nor the compared quantity, which
        also left Maximum_Foreign_CPU_Percent unlinked. Two harnesses that both pause
        do not deadlock as claimed; they alternate between pausing and resuming.

        Editorial. "This matters most" and "Without it" both referred back to
        something unnamed. Both now name their subject.

        Controlled language. "Sharpens attribution" was figurative and is now
        "narrows attribution to the placed CPU and its SMT siblings". "A run that
        repaired itself reports that fact" personified the run; the report is the
        actor, and it states counts.

        Verified with ./scripts/build-site.sh and the site checker, which passes 144
        HTML files. All fourteen API links resolve to an existing anchor in the
        generated GNATdoc output, and each target matches the entry the API search
        index gives for that entity. No sentence in the section exceeds the 25-word
        review signal.

      6. edf788ef
        Problem: The guide does not say the host controls are opt-in

        The interference section described three capabilities without saying that a
        run acquires none of them unless it asks. BENCH 07 states that contract for
        the preflight gate, and the page marks the default value of a choice where one
        exists, as it does for Equal_Time and Balanced_Rounds. The new section did
        neither, so a reader could not tell that enabling the watch alone changes
        nothing about the collected data.

        The claim file was also absent. The page named three environment variables but
        not the one path that other tools must agree on, leaving the coordination
        surface a click away in the convention document.

        Solution: State the defaults, the claim path, and the budget interaction

        Observe is now marked as the default response, in the form the page already
        uses. The closing paragraph mirrors BENCH 07: the watch, placement, and the
        host claim are disabled by default, so an existing run acquires no new wait or
        failure condition. The opening sentence calls the watch optional where the
        reader first meets it.

        The claim paragraph names /tmp/host-cpu.lock, the Path field that overrides it
        for one run, and the HOST_CPU_LOCK_PATH variable that overrides it for every
        tool following the convention. An earlier draft named only the variable, which
        implied it was the sole override; the technical review caught that against
        Resolved_Path and Try_Acquire.

        The Window row gains the limit that qualifies it. A window covers whole units,
        so a window spanning many short samples can exceed Maximum_Retakes on its
        first discard. Collection then continues under Observe and reports the
        exhausted budget, which otherwise looks like the response never ran.

        Numeric field defaults are deliberately not repeated here. No other section of
        the page tabulates them, every field now links to its generated entry, and a
        duplicated value is one that can go stale.

        Verified with ./scripts/build-site.sh and the site checker, which passes 144
        HTML files. All fifteen API links resolve to an existing anchor, and each
        target matches the entry the API search index gives for that entity, including
        the ambiguous Path simple name, which resolves to Host_Lock_Policy.Path. No
        sentence in the section exceeds the 25-word review signal, and no entity is
        linked twice.

      7. 4fbe5020
        Problem: The recording smoke test separates its workloads with a delay

        recording_smoke drives two benchmarks from four tasks and asserts that the
        slow benchmark's recorded median wall time exceeds the fast one's. The
        separation comes from delay 0.000_2 against delay 0.000_8. A relative delay
        is rounded up to the host timer tick, and on a Linux kernel with a coarse
        tick both requests wake at the same boundary near 3 ms. A four-task probe
        with no recorder involved shows the first iteration of each task honoring
        the request and every later one landing on the same plateau:

        0.0002 s: 323 3710 2829 2972 3069 2947 ... (us)
        0.0008 s: 1167 3307 2482 3625 2793 3045 ... (us)

        The two recorded medians then arrive at 2.98 ms and 2.99 ms, ordered by
        scheduling noise alone. On Ubuntu 24.04 with GNAT 16.1.0 on aarch64 the
        assertion fails about half the time: 9 of 20 runs on a clean checkout. macOS
        resolves the two delays apart, which is why the test has held there. The
        independent comparison checked two assertions below rests on the same
        separation and fails with it.

        Solution: Separate the distributions by work the workers perform

        Each worker spins a volatile rotate-and-xor accumulator, 20_000 rounds for
        the fast benchmark and twenty times that for the slow one, the idiom the
        file's concurrent PMU-session block already uses. That is roughly 33 us
        against 680 us, a twentyfold gap read by a nanosecond wall clock, so no
        timer resolution enters the measurement. It also costs less than the
        sleeping it replaces: the slow workers take about 14 ms rather than 60 ms.

        The assertion stands, since the ordering is the invariant worth holding, but
        its message now carries both medians so a failure on an unusual host reports
        numbers rather than a verdict.

        Verified on the failing environment, an Ubuntu 24.04 container with GNAT
        16.1.0 on aarch64: 30 of 30 runs pass where HEAD fails 9 of 20 in the same
        container, 20 of 20 under a two-CPU quota, and 10 of 10 with 24 competing
        spinners on that quota. scripts/test.sh passes three times from a fresh
        source export there and once on macOS. A calibration probe over 105 further
        trials across those CPU configurations held the ratio between 14x and 30x
        with no inversions and Relative_Change_Percent positive throughout.

      8. ae5b52d7
        Problem: A group snapshot cannot say whether its event loop is busy

        Flyology.Observability.Group_Snapshot carries thirty fields covering queue
        depths, wait categories, and cumulative counters, but none of them reports how
        much of an event loop's time was spent doing work. Pool imbalance is therefore
        invisible from outside the process: a group with a deep ready queue and a group
        that is idle produce the same evidence once their momentary queue depths match.
        Made_Progress detects a stalled loop but not a saturated one, and its comment
        already records why a per-dispatch clock read was rejected as the answer.

        Solution: Time the poller wait a loop takes when nothing is ready

        An event loop enters Wait_Batch only when its ready queue is empty, so the idle
        path is both the exact complement of the loop's working time and a path a busy
        loop never repeats. The scheduler stamps the wait before releasing the group
        lock and closes it after reacquiring, keeping the in-progress wait in the group
        so an observer adds it rather than charging a long block as busy time. Nothing
        is added to dispatch, context switch, or any other hot path.

        Group_Snapshot gains Uptime_Nanoseconds, Idle_Nanoseconds, and Idle_Waits, and
        the runtime snapshot ABI moves to version 6. Idle time is clamped to uptime and
        both come from one clock reading, so callers can always take the difference or
        the ratio. tests/native/process_lifecycle_probe.c pins that ABI and its layout,
        and moves with it.

        The cost is measured rather than asserted. runtime_callback_bench adds
        poller_idle_cycle for the instrumented path and monotonic_clock_read for the
        unit of work it adds; benchmarks/idle_wait_rate reports the rate a loop
        actually reaches, because the effect is far below what a differential timing
        run resolves on this host. On macOS/AArch64 a reading costs about 20 ns, a
        socket ping-pong reaches roughly 32,000 to 38,000 waits per second per loop,
        and a loop doing nothing else reaches roughly 120,000 to 160,000: under 0.2%
        and under 0.7% of a loop's time respectively.

        Checks run: ./scripts/test.sh (pass, including the new
        observability_utilization_smoke), ./scripts/docs.sh (pass, no new warnings),
        ./scripts/bench-runtime.sh.

      9. 6c4bfc3c
        Problem: The guide cannot tell a reader whether a group is busy

        Step 10 of the guide lists the readings that diagnose a group, but every one of
        them describes queue contents. A reader who wants to know whether an event loop
        is saturated has no entry to follow, and the utilization fields the runtime now
        publishes appear only in README.md and the generated API reference.

        Solution: Document loop utilization where the guide diagnoses a group

        A new subsection explains what the runtime measures, why the subtraction is
        always valid, and the two readings that look alike: a group whose tasks all
        wait resembles a group with nothing to do, and a task that never suspends keeps
        its loop out of the poller and reports as fully busy. A decision row places the
        measure next to the queue-depth readings it qualifies. The cost paragraph names
        the measured figures and the script that reproduces them, rather than asserting
        that the accounting is cheap.

        The worked example is compiled and run by tests/guide_utilization_example.adb.
        The first draft of that example did not compile, because Counter is a modular
        subtype and the subtraction needs a use type clause the guide had not shown. A
        test main is the only check that keeps a printed example honest about the
        visibility a reader must supply.

        Checks run: ./scripts/test.sh (pass, including the new
        guide_utilization_example), ./scripts/build-site.sh, and check-site.mjs over
        the built site as CI runs it.

      10. fb881640
        Problem: The utilization copy states a rule that does not hold

        The website/AGENTS.md technical review is required for any changed capability,
        limit, or timing claim, and running it on the new guide section found four
        faults.

        Two are wrong rather than unclear. The guide told a reader that `Counter` needs
        a `use type` clause because the subtype is modular; the clause is needed
        because the operators of a type declared in another package are not directly
        visible, so the stated rule teaches the wrong thing. The guide also said an
        event loop waits in its poller only when no task can run, but the loop polls
        with a zero timeout while work is ready, and the same section counts that
        polling as busy time.

        The remaining two narrow a claim that had become broader than the code.
        "Dispatching, polling with work ready, or running task code" reads as an
        exhaustive account of a loop's busy time and omits timer promotion, file
        submission, and cancellation processing. That wording appeared in the guide,
        README.md, and the Group_Snapshot field documentation, so all three change
        together. `Group_Snapshot` and `Snapshot` appeared only inside the code block
        and were linked nowhere in prose, which the API-link rule does not allow.

        Solution: Correct the two faults and narrow the two broad claims

        The editorial and controlled-language passes contributed three further changes:
        one repeated paragraph opening, "idle fraction" used before the section
        introduces it, and "reading" carrying both a clock read and a snapshot.

        Checks run: ./scripts/docs.sh (pass, no new warnings),
        ./scripts/build-site.sh with check-site.mjs over the built site,
        and observability_utilization_smoke, guide_utilization_example, and
        observability_smoke rebuilt and re-run.

      11. bca8ad7f
        Problem: Previewing the built site needs an ad-hoc server command

        scripts/build-site.sh writes the complete site to build/site, but nothing
        records how to serve it. Reading a guide page as it will be published means
        inventing a static-server invocation each time, and picking a port that does
        not collide with a development server already running.

        Solution: Record a launch configuration that serves the built site

        The entry serves build/site on port 8231. It reads the build output and does
        not produce it, so run scripts/build-site.sh first and again after editing
        anything under website/.

        Checks run: served build/site through the entry and loaded the guide page.

      12. 104d406f
        Problem: macOS L1 detection reports efficiency-core capacity

        The macOS body queries the flat hw.l1dcachesize sysctl. On a heterogeneous
        Apple silicon host that name reports the efficiency-core capacity, not the
        performance-core capacity: one 12P/4E host reports 65536 bytes for the flat
        name against 131072 for hw.perflevel0.l1dcachesize. Flyology_Cachelines.
        L1_Data_Cache_Size therefore reports half the performance-core L1d capacity,
        and L1_Data_Cache_Slots derives its slot count from that halved value.

        The reader also assumed every queried name stores a 64-bit value. It read
        each name into one 64-bit object and accepted a short reply, so a 32-bit
        value was correct only because Darwin is little-endian and the object was
        zero-initialized. The per-level names are 32-bit.

        Solution: Prefer the highest performance level and read the reported width

        macOS 12 and later describe a host whose cores are not identical as ordered
        performance levels, where hw.perflevel0 is the highest-performing level. The
        macOS body now queries hw.perflevel0.l1dcachesize and falls back to the flat
        name only on a host that publishes no performance level, such as macOS 11 and
        earlier or an Intel Mac. Querying hw.nperflevels first would add nothing: the
        per-level name exists exactly when the host publishes performance levels.
        Hardware_Cache_Line_Size is unchanged, because Darwin publishes no per-level
        line size and both Apple silicon core types use the same line.

        The public API keeps its Cache_Query_Result surface. Reporting per-level
        geometry is a separate design question, and it should not ride along in a
        detection correctness fix.

        The sysctl reader moves into a new private Flyology_Cachelines.Macos child,
        mirroring the existing Flyology_Cachelines.Linux split between mechanism and
        policy. It requests each name's stored width before reading the value and
        rejects any other width, so a 32-bit name, a 64-bit name, a string, and an
        absent name are all handled without depending on byte order. Failed and
        malformed queries still degrade to Unavailable rather than raising.

        The GNATdoc comments on L1_Data_Cache_Size and L1_Data_Cache_Slots, the crate
        README, and the website cachelines guide now state that a host whose cores are
        not identical reports one core type, and which one each platform reports. A new
        macOS detection test mirrors the Linux one: it exercises the sysctl reader
        directly and checks that the reported capacity is the highest performance level
        the host publishes.

        Checks run: ./flyology_cachelines/scripts/test.sh (the native test now reports
        131072 bytes of L1 data cache on a 12P/4E host, and the new macOS detection
        test passes) and ./flyology_cachelines/scripts/docs.sh (zero GNATdoc warnings).

      13. d3af8647
        Problem: The Linux detection test requires an optional mechanism

        Flyology_Cachelines.Linux_Testing asserts that both Detect_From_Sysconf and
        Detect_From_Sysfs report a value. Only their composition is guaranteed:
        glibc answers _SC_LEVEL1_DCACHE_SIZE and _SC_LEVEL1_DCACHE_LINESIZE from
        CPUID on x86-64, but reports zero on aarch64, where sysfs is the only
        mechanism. Detect already treats sysconf as optional and falls back to
        sysfs, so the test is stricter than the code it covers.

        The test therefore fails on aarch64 Linux with "sysconf cache detection
        failed". CI runs ubuntu-latest on x86-64, where sysconf answers, so the
        failure is invisible there. It reproduces on aarch64 Linux, which AGENTS.md
        tells contributors to prefer on Apple silicon because it is native and
        faster.

        Solution: Require the composition and check each available result

        Run now requires that at least one mechanism reports a value, and checks
        consistency only for a mechanism that reported one. That is what the
        production detector promises: it composes sysconf and sysfs, and returns
        Unavailable only when neither answers.

        Checks run: the crate suite on aarch64 Linux in a container, where the
        detection test now passes, and on macOS, where it is not built.

      14. 04658ed7
        Problem: Linux cache detection describes only CPU 0

        Flyology_Cachelines.Linux reads one L1 data-cache geometry: sysconf answers
        for the calling CPU, and the sysfs fallback reads cpu0. A host whose cores
        are not identical has more than one geometry, and neither mechanism says
        which core the reported one belongs to, or that others exist.

        macOS already publishes ordered performance levels, so the macOS body can
        prefer the highest-performing one. Linux publishes per-CPU descriptions and
        no single ordering, so the equivalent information has to be derived before
        any public per-core-type query can work on both platforms.

        Solution: Group CPUs into core classes and record what ordered them

        Detect_Core_Classes enumerates the CPUs the host lists as present, reads
        each one's L1 data-cache geometry and capacity, groups CPUs reporting
        identical values into a class, and counts each class.

        Classes are grouped on capacity and geometry together. Grouping on geometry
        alone merges two core types that happen to share an L1 data-cache size,
        which real designs do.

        Ordering uses whichever key separates the classes, and Core_Classes reports
        which one did, so a caller can tell an authoritative order from an inferred
        one:

        - Host_Reported: the kernel's per-CPU capacity values separated them.
        Capacity is the scheduler's own measure of relative CPU performance and
        accounts for microarchitecture and clock. Architectures selecting the
        generic topology code publish it under cpuN/cpu_capacity.
        - Inferred: no capacity separated them, so they are ordered by descending
        L1 data-cache capacity. That holds on current hybrid parts and carries
        no meaning on a host whose classes differ some other way. x86-64 does
        not publish capacity, so its hybrid parts land here.
        - Unordered: fewer than two classes, or nothing separated them.

        Cores and CPUs are counted separately. SMT siblings share one L1 data cache,
        so the cache's sharing list identifies which CPU represents a physical core.
        Counting logical CPUs as cores overstates a 24-core host with two threads
        per core by a factor of two.

        Detection fails closed. A missing or malformed CPU list leaves only CPU 0 to
        enumerate, enumeration is bounded, a CPU whose description cannot be read is
        skipped, and a host reporting more classes than the table holds reports none
        rather than a table that silently omits a class.

        Detect_Core_Classes takes the CPU root as a parameter defaulted to the real
        sysfs path. Grouping, ordering, and the SMT distinction cannot be reached on
        a uniform test host, so the detection test drives them with committed
        fixture trees: two classes separated only by capacity, two classes separated
        only by geometry with the smaller listed first, SMT pairs sharing one cache,
        and a CPU list with a gap.

        Nothing calls Detect_Core_Classes outside the test yet. The public
        per-core-type query, and the elaboration cost of walking every CPU, belong
        to the change that adds that query.

        Checks run: the crate suite on aarch64 Linux in a container and on macOS.
        Detection was also replayed against captured CPU descriptions from a 48-CPU
        x86-64 host with two threads per core, which reports 24 cores against 48
        CPUs and no capacity, and from an 80-CPU aarch64 host, which reports 80
        cores against 80 CPUs and a published capacity.

      15. ba8438da
        Problem: Cache queries cannot name a core class

        Flyology_Cachelines reports one L1 data-cache capacity. A host that combines
        core types has one per type, so a single value silently describes whichever
        type the platform body happened to pick and gives a caller no way to ask
        about the others, or to learn that others exist.

        The two platforms also disagreed. macOS reported the highest performance
        level, while Linux reported whichever cache its own mechanism described:
        sysconf for the calling CPU, sysfs for cpu0. The same call therefore meant
        different things on the two platforms.

        Solution: Make the core class an explicit parameter of every cache query

        Core_Class names one class of cores that report a single cache geometry.
        Core_Class_Count reports how many the host distinguishes, Core_Class_Cores
        and Core_Class_CPUs describe each one, and L1_Data_Cache_Size and
        L1_Data_Cache_Slots take the class they describe. The parameter defaults to
        Fastest_Core_Class, so existing calls keep compiling and now mean the same
        thing on both platforms: the class the host ranks highest.

        Core_Class_Ordering reports what produced that rank, because it is a host
        fact on some platforms and the crate's inference on others. macOS performance
        levels and the Linux per-CPU capacity values are Host_Reported. A host
        publishing no rank is Inferred, ordered by descending L1 data-cache capacity.
        Fewer than two classes is Unordered.

        Cores and CPUs are reported separately. Sibling CPUs under simultaneous
        multithreading share one core's L1 data cache, so a 24-core host with two
        threads per core reports 24 cores and 48 CPUs in one class.

        Hardware_Cache_Line_Size takes no class. macOS publishes no per-class line
        size, and the core types of current heterogeneous parts share one line size,
        so a per-class query would have one answer to give.

        The host is now inspected on first use rather than during elaboration.
        Describing every class means reading one description per CPU on Linux, which
        measures 14 ms for 48 CPUs and 24 ms for 80. A program that links this crate
        and never asks about the host should not pay that at startup. The inspection
        is idempotent, so a race on the first query can duplicate work but cannot
        produce a value neither caller computed; the ready flag is atomic and is set
        after the result is stored.

        Flyology_Cachelines.Platform now answers one Detect call describing the whole
        host, and the root package body owns the single memoization. The two Linux
        bodies share one translation and differ only in what they report when sysfs
        describes nothing: the x86-64 body can still read the calling CPU through
        CPUID. Flyology_Cachelines.Linux drops its own class and ordering types in
        favour of the public ones, so the crate has one Core_Class.

        The website cachelines guide is corrected alongside the API. Adding the Class
        parameter changed the generated GNATdoc anchors for L1_Data_Cache_Size and
        L1_Data_Cache_Slots, so the guide's links to them became dangling fragments;
        both now point at the regenerated anchors. The guide also claimed detection
        happens during package elaboration, which is no longer true. The new entities
        are linked to their generated entries on first mention.

        Checks run: the crate suite on macOS, where a 12P/4E host reports two
        host-ordered classes of 131072 and 65536 bytes across 12 and 4 cores; on
        aarch64 Linux in a container; and on an x86-64 Linux host with 24 cores and
        two threads per core, which exercises the CPUID body and reports 49152 bytes
        across 24 cores and 48 CPUs. GNATdoc builds with no warnings.

      16. 9782c81b
        Problem: The shared L2 cache is not reported

        Flyology_Cachelines reports L1 but not L2, so a caller sizing a working set
        against the level it will actually spill into has nothing to read.

        The flat sysctl this crate would naturally have used is wrong in the same way
        hw.l1dcachesize was, and by a larger factor. On a 12P/4E Apple silicon host
        hw.l2cachesize reports 4194304, the efficiency cluster's cache, against the
        performance cluster's 16777216. Adding L2 before core classes existed would
        have reproduced the original defect at four times the size instead of two.

        Reporting a capacity alone would also mislead. L2 is rarely private: that same
        host shares 16 MiB across six performance cores and 4 MiB across four
        efficiency cores, so neither figure is a per-core budget.

        Solution: Report L2 capacity and how many cores share it, per class

        L2_Cache_Size and L2_Sharing_Cores take the same core class as the L1
        queries. A sharing count of one means the cache is private to a core; a
        larger count means the reported capacity is divided among that many cores.
        The GNATdoc on each function points at the other, because reading either
        alone invites the per-core mistake.

        macOS reads hw.perflevelN.l2cachesize and hw.perflevelN.cpusperl2. Linux
        reads the level 2 entry of each CPU's cache description, counting the CPUs
        its shared_cpu_list names. Both counts arrive as logical CPUs and become core
        counts through the class's own threads-per-core ratio, so a host with two
        threads per core does not report twice the cores sharing a cache.

        Parsing a CPU list needs more than its leading index, so the Linux body gains
        List_Count, which sums the single indexes and inclusive ranges a list names.
        Describing L2 costs no extra file reads: the level 2 entry is found in the
        same pass over the cache indexes that already locates the level 1 data entry.

        The website cachelines guide gains the same pairing, with both names linked
        to their generated entries.

        Checks run: the crate suite on all three supported targets. A 12P/4E macOS
        host reports 16777216 bytes across 6 cores for its performance class and
        4194304 across 4 for its efficiency class, and the macOS test asserts that
        these come from the performance level rather than the flat name. An aarch64
        Linux host reports 16777216 across 6 cores. An x86-64 Linux host with 24
        cores and two threads per core reports 2097152 across 1 core, where sysfs
        gives 2048K shared by CPUs "0,24"; that run also compiles the CPUID body,
        which builds nowhere else. Fixtures cover a per-class shared L2, an L2 shared
        across SMT siblings, and a private L2. GNATdoc builds with no warnings.

    4. 9782c81b updated to 7be049fcindex 6e2db0ef

      1 source commit

      1. 7be049fc
        Problem: A stalled package mirror hangs CI instead of failing it

        The two OpenSSL install steps in the test job carried no bound, so a mirror
        that stops answering leaves apt waiting rather than returning an error. On
        2026-08-19 run 32297071503, job 96211136305 sat on "Install OpenSSL 3 on
        Linux" for 32 minutes and had to be cancelled by hand; it was the only check
        blocking PR #49. Its log shows apt-get update fetching noble-security
        InRelease at 20:13:04 and producing no further output until cancellation. The
        macOS half of the same job passed, so nothing was wrong with the tests.

        Left alone the job would have run to GitHub's six-hour default. Nothing else
        in either workflow was bounded either: the checkout, the Alire install, the
        index configuration, the Java and TLA+ downloads, and the GNATdoc install all
        reach the network under the same default, and no job in this repository
        declared a timeout at all, unlike the sibling repositories.

        Solution: Bound every job and every step that reaches the network

        Each job now declares a timeout-minutes, and so does each step that fetches
        something. The bounds are generous multiples of what healthy runs measure
        over the last 60 successful runs of each workflow, so they can only fire on a
        stall. Jobs: test observes at most 17 minutes on macOS and 11 on Linux and is
        bounded at 60; proof observes 6 minutes and TLA+ 7, both bounded at 30; the
        pages build observes 69 seconds and is bounded at 20, its deploy 10 seconds
        and bounded at 15. Steps: everything network-touching is bounded at 10
        minutes against observed maxima of 1 to 6 seconds, except the Alire install,
        which downloads the toolchain, observes 100 seconds, and is bounded at 15.

        A step timeout alone would only have converted the 32-minute hang into a
        10-minute one, because the stall is inside a single apt-get update that never
        returns. That command is now capped per attempt with timeout(1) and retried
        twice with 15 and 30 second backoff, so one unresponsive mirror costs a
        retry rather than the job. The install that follows is capped as well but not
        retried: a package that cannot be resolved should fail on the first try. The
        worst case is three 120-second attempts plus a 10-second kill grace, 45
        seconds of backoff, and a 190-second install, which is 10m25s and lands
        inside the 12-minute step bound, so the annotation naming the transient
        mirror is what the log ends on rather than a bare cancellation.

        GNU timeout is used directly rather than scripts/run-with-timeout.sh. That
        helper exists for portability to macOS, and this step is Linux-only.

        The TLA+ download gains --connect-timeout 30 and --max-time 120 alongside its
        existing --retry 3, because curl retries a failed transfer but not a stalled
        one, and --max-time resets per attempt. Four bounded attempts stay inside the
        step's 10 minutes.

        Build, test, proof, and model-checking steps keep no step bound. Their
        duration is workload-dependent, a bound sized for them would be a performance
        budget rather than a stall detector, and the job timeout already covers them.
        Nothing about what is installed, or how anything is built or tested, changes.

        Checks run: both workflows parse. The retry script was extracted from the
        committed YAML and driven under bash -e against stub apt-get invocations for
        five outcomes: first-try success runs one update and one install; two
        failures then success runs three updates and installs; three failures exit 1
        with the annotation and never install; an install failure propagates its exit
        status without retrying; and exit 124, which is what timeout(1) reports when
        it kills a stalled command, is treated as retryable. The real commands were
        then run in an ubuntu:24.04 container on coreutils 9.4, the runner's version:
        the bounded update succeeds, interrupting one mid-flight reports 124, a
        retry after that kill still succeeds rather than inheriting a poisoned apt
        state, and the bounded install still yields OpenSSL 3.0.13 through pkg-config.

        The convention is recorded in AGENTS.md so it holds for new steps, and it
        matches the job-level timeouts already used in flyology-http and
        gnat-patches, whose install steps want the same treatment.

        Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

    5. 7be049fc updated to a53da35dindex b5569962

      1 source commit

      1. a53da35d
        Problem: The allocators dependency accepts any version

        The allocator crate is developed alongside the runtime in this repository and
        released on the same development line, but the dependency on it is declared as
        "*". Nothing stops a dependent from resolving an allocator release built for a
        different line, and the index has been carrying a tighter constraint by hand to
        compensate.

        Solution: Constrain allocators to its development line

        Declare the line the allocator crate actually publishes, so the constraint
        travels with the manifest instead of being reapplied wherever it is indexed.

        Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

    Compare source revisions
    Development update

    flyology_debug 0.1.1-dev

    5 updates: 91d6a0f6 through a53da35d

    Bounded in-memory tracing and gauges for Ada

    Manifest fields
    origin
    Show all 5 updates
    1. 91d6a0f6 updated to 9a24bf68index 510cfcf6

      39 source commits

      1. 40849230
        Problem: DNS smoke depends on hosted-runner timing

        The functional loopback checks use retry intervals too narrow for occasional macOS hosted-runner stalls. An early client exception also waits behind cancellation coordination and loses the operation that failed, leaving only a generic lifecycle assertion.

        Solution: tolerate stalls and report DNS smoke stages

        Use functional smoke deadlines that accommodate runner scheduling, let coordination observe early client completion, and report the execution model and operation stage for unexpected exceptions. The dedicated DNS resilience smoke retains narrow deadline coverage.

      2. 347604c6
        Problem: Codex and Claude usage across the Flyology workspace is difficult to audit

        Session logs are distributed across project checkouts, worktrees, sister
        repositories, and nested agent sessions. Their token counters also contain
        cached input, repeated cumulative records, inherited history, and duplicated
        Claude message entries, making straightforward aggregation inaccurate.

        Solution: add a portable incremental AI usage audit

        Add a self-contained PEP 723 Python script that discovers the workspace from
        its containing repository and scans associated Codex and Claude Code logs,
        including worktrees, subagents, and workflows.

        Deduplicate cumulative and inherited records, categorize base input, cache
        reads and writes, output and reasoning tokens, and estimate API-style costs
        using model-specific pricing. Persist JSON cursors and daily aggregates so
        subsequent runs process only new log records.

        Provide summary, daily, weekly, provider, and model breakdowns with JSON
        output, date filtering, configurable paths and timezone, state rebuilding,
        and integrity diagnostics.

      3. 73925055
        Problem: Flyology website presents Runtime as the umbrella

        The landing page, navigation, guide index, and machine-readable documentation center Flyology Runtime while standalone libraries share the project identity without depending on it. Visitors cannot reliably distinguish the runtime core, runtime-dependent protocol libraries, and independently adoptable components, and several component documentation paths are missing or placed under the wrong section.

        Solution: Present Flyology as the project and Runtime as its core

        Reorganize the landing page around the project umbrella, add focused Runtime and Libraries pages, move Guide, Architecture, and the main API under Runtime, separate standalone documentation from the Runtime guide, link each published component Guide and API, fix the scrollable guide topic rail, and align README, product, design, journal, build assertions, and llms.txt with the same dependency model.

      4. 6cb6887f
        Problem: Flyology package discovery and maturity guidance compete

        The redesigned project pages repeat the experimental label in several nearby locations while the curated Libraries directory has no path to the complete package index. Readers see redundant maturity warnings but cannot easily reach version, dependency, availability, and compiler-build records for every published package.

        Solution: Clarify maturity guidance and link the complete crate index

        Keep experimental status in the primary explanatory context, make constraints and adoption guidance more direct, and link crates.flyology.org from the Libraries introduction, footer, and llms.txt documentation map.

      5. 4738d656
        Problem: The crate index is absent from shared site footers

        Only the Libraries page exposes the complete package catalogue in its footer. Readers arriving on Runtime, Guide, Architecture, Journal, or the project overview have no equivalent utility path to package versions, dependencies, and availability records.

        Solution: Add the crate index to every shared footer

        Place the Crate index utility link first in each hand-written footer, including the journal entry template, while retaining every page-specific navigation link.

      6. 5b7c3925
        Problem: Cancellation promptness is asserted as a per-round wall-clock bound

        Check_Parent_Cancellation_Is_Prompt in tests/task_scope_faults_smoke requires
        every one of 16 rounds to propagate parent cancellation within 5 ms.
        Propagation crosses two lightweight-task wakes, and a contended shared runner
        can deschedule either of them for milliseconds, so the check reports host
        scheduling as often as it reports the mechanism. CI run 32100324387 failed
        this assertion on its first attempt and passed on a rerun of the identical
        commit 71df9ed, whose only change is .github/workflows/pages.yml. Locally,
        96 spinning processes on 16 cores plus nice -n 20 reproduce the failure in
        2 of 30 runs, and 1280 rounds measured under that load put the median at
        78 us with 0.9 per cent of rounds past 5 ms: the mechanism is prompt and the
        bound is reporting the host. A bare pragma Assert also names only a source
        line, so a real regression is indistinguishable from a stalled round.

        Solution: Require most rounds to be prompt, bound the rest, and report them

        The check now measures all 16 rounds, requires at least 10 of them within
        1 ms, and requires no round past a 0.5 s sanity ceiling. That is a stronger
        claim about the mechanism rather than a weaker one. The retired 10 ms polling
        monitor spreads its latency across its period and places about 1.6 of 16
        rounds inside 1 ms, so it clears the new bar about once in two million runs
        against once in sixty-five thousand for the old whole-round 5 ms bound;
        reinstating that monitor put 0 of 16 rounds inside 1 ms and failed the new
        check on all five idle runs. Under the load that failed the old check in
        11 per cent of runs, the new check passed 60 of 60. A failing round set is
        printed to standard error so the next failure names the rounds and their
        latencies instead of only the assertion line.

      7. 857820c4
        Merge pull request #47 from flyology-ada/claude/gifted-sanderson-75002d

        Problem: Cancellation promptness is asserted as a per-round wall-clock bound

      8. 5dfa0d25
        Problem: Broken site links reach main before anything checks them

        The site check that validates local links and fragment targets runs only in
        the Pages workflow, which triggers on a push to main and on manual dispatch.
        No pull-request workflow builds the site, and ci.yml has no site job, so a
        change that breaks a link passes every check a reviewer sees, merges, and
        then fails the Pages build on main. The site stops publishing at the point
        where the mistake is hardest to attribute.

        The hand-written pages carry 457 links into generated GNATdoc entries across
        eleven guide and architecture pages. GNATdoc names each entry by a hash of
        the declaration, so changing a public subprogram's parameters gives it a new
        anchor and silently strands every hand-written link to it. Editing the
        surrounding documentation comment does not, which makes the failure easy to
        miss: prose edits are safe, and a signature change quietly is not.

        Solution: Build and check the site on pull requests

        The Pages workflow now also runs on pull_request. The build job is
        unchanged for a push, and on a pull request it builds the site and runs the
        same link check without touching Pages: configuring Pages, uploading the
        artifact, and the deploy job are all skipped. A pull request therefore needs
        no Pages permission, which also keeps the job usable from a fork.

        Concurrency now groups per ref. One group for every event serialized
        unrelated pull requests behind each other and behind a deploy. Pushes to main
        still share one group and are still never cancelled; a pull request cancels
        its own superseded runs.

        This adds a toolchain and GNATdoc build to each pull request, which is the
        cost of resolving generated anchors: the check can only confirm a fragment
        exists by generating the page that defines it.

        Checks run: the workflow parses, has no tabs, guards exactly the three
        Pages-specific steps, and keeps the link check unguarded. check-site.mjs was
        confirmed to catch this class of breakage against a page carrying one stale
        API fragment, where it reports "missing fragment target" and exits non-zero.
        This pull request triggers the new job, so its own run is the end-to-end
        check.

      9. 252f4fd7
        Problem: Ada programs cannot see the host's memory-node structure

        A machine with more than one processor package attaches memory to each of
        them, and memory attached to the package a thread runs on is reached faster
        than memory attached to another. Nothing in this repository reports that
        structure. Ada itself does not describe it either: System.Multiprocessors
        covers processors and dispatching, and the language has no notion of a
        memory node at all.

        Without it, a program that wants its work near its memory has nothing to
        place against.

        Solution: Adopt flyology_numa as a nested standalone crate that reports it

        The crate reads the host description and reports memory nodes, the
        processors attached to each, firmware-declared distances, per-node memory,
        and processor packages. It does not place memory; that is a separate
        question this crate does not answer.

        Three decisions shape the interface.

        Topology queries are total. A host with no memory-node structure reports one
        node holding every processor, because such a host genuinely has one memory
        domain. Support distinguishes a description that was read from the host from
        that single-domain description. Individual facts a host does not answer use
        the existing variant-record convention with Value_Or, so a caller names its
        own fallback rather than receiving a plausible number.

        Online and permitted nodes are reported separately. A container is shown the
        whole machine's node list while a control group restricts what it may
        allocate on, so the host description alone does not establish permission.
        Allowed_Nodes intersects the description with Mems_allowed_list from the
        process status file.

        Node and processor numbers are the host's own, and sparse. They match sysfs
        paths and numactl output, so a reported number is the number to look up
        elsewhere. To_CPU performs the Ada processor mapping GNAT applies unchecked,
        and declines when the host's numbering has a gap the mapping cannot carry.

        A description this crate cannot read is reported as a shortfall rather than
        guessed at. Support.Complete goes false when any part of the description was
        refused: a node or processor number beyond the represented range, a list
        naming more ranges than the reader holds, an unreadable processor list, or a
        permitted-node list the host named and the reader did not understand. The
        distinction that matters is between a node with no processor attached, which
        is an ordinary memory expander, and a node whose processor list could not be
        read, which is not known to have none. A description that names nodes but
        attaches no processor to any of them is refused outright, because every
        machine has a processor.

        The sysfs reader names the directories it reads instead of assuming them, so
        it is host-independent text processing that compiles and runs everywhere.
        This departs from flyology_cachelines, which keeps all Linux code under a
        Linux source directory and tests only the host it runs on. The interesting
        cases cannot be reached that way: a development machine has one node and a
        container on one is single-node too. Twelve recorded descriptions under
        tests/fixtures cover two packages of one node each, two packages each
        divided into two memory nodes, a node carrying memory with no processor
        attached, sparse node numbering, a control-group restriction, a gap in
        processor numbering, an older host naming only its ordinary memory, and five
        descriptions the reader must refuse or report as incomplete. All are
        exercised on macOS, which has none of them.

        Set algebra lives in its own unit rather than the root body because
        discovery runs during the root package's elaboration and cannot call back
        into the body it is elaborating. Each step of the discovery chain names the
        body it needs with pragma Elaborate, so the ordering does not rest on the
        binder inferring it. Elaborate_All would not serve: its closure reaches back
        through the platform spec to the root body itself.

        A processor list is bounded at one range per processor rather than at 64,
        because a host that enumerates processors round-robin across its nodes gives
        each node a list of single-processor ranges.

        Verified with ./flyology_numa/scripts/test.sh on macOS aarch64 from a clean
        tree: both the host suite and the fixture suite pass, and clean builds of
        the linux, macos, and unsupported platform bodies through the crate's
        host-selection scenario variable emit no warnings, style diagnostics, or
        errors.

      10. 376d2481
        Problem: Flyology_NUMA reports memory nodes but cannot use them

        The crate describes which memory nodes a host has and which processors are
        attached to each. A program that wants its work near its memory can read
        that and then do nothing with it: there is no way to ask that a region's
        pages be drawn from a chosen node.

        Solution: Add Flyology_NUMA.Placement over the kernel's memory-policy calls

        Placement is a separate package from the reporting one because the two fail
        differently. Reading a description always succeeds; acting on one often does
        not. Support reports which of three states applies before anything is
        attempted, and every operation reports its own outcome rather than raising.

        The third state is the one worth having. A host may have no placement
        interface, or it may have one this process is refused. A container sandbox
        commonly refuses these calls while the machine underneath has memory nodes
        that other processes are using, and reporting that as a host without the
        facility would be wrong. Denied is therefore distinct from Unsupported_Host.
        The two are told apart by what the host said about itself rather than by the
        error number alone, because a sandbox may answer a refused call by claiming
        the call does not exist: a host that described its own memory nodes has the
        calls that act on them, so a refusal from such a host is a denial.

        Support is settled on the first call that needs it rather than while the
        package elaborates. A sandbox that answers a refused call by ending the
        process would otherwise end any program that merely links this crate, even
        one that never places memory.

        Apply_To places a range, Apply_To_Thread places what the calling thread
        allocates from then on, Node_Of_Address reports where a page ended up, and
        Permitted_Nodes asks the host afresh rather than reusing what it said
        earlier. A range must begin on a page boundary because placement acts on
        whole pages; an unaligned range is refused before the host is asked.

        Three details of the kernel interface are easy to get wrong and silent when
        got wrong, so each is handled deliberately.

        The node-bit count is decremented by the kernel before the mask is read, so
        passing the number of bits meant would drop the highest node. Placement
        passes one more than that, which names every node this crate represents
        while still asking for only the eight bytes the mask has. Reading the
        permitted nodes is bounded differently again: the kernel refuses a count
        below the number of nodes the host could ever have, counting nodes that are
        merely possible rather than online, so that read uses a buffer covering the
        largest node count Linux can be built for.

        Two policies take no node set, and the kernel rejects either of them when
        one arrives. Passing the set a caller naturally has to hand would therefore
        fail, so the set is dropped before the host sees it and the interface's
        promise that it is ignored is kept.

        The preferred policy takes a single node, not a set. The interface documents
        that only the lowest-numbered node is preferred rather than implying the
        whole set contributes.

        No C library wraps these calls. Their manual pages document a separate
        library's wrappers, not the one every program already links, so they are
        reached through the generic system-call entry point. That entry point is
        variadic, which is one of the reasons this repository admits C, but GNAT's
        variadic convention reaches it correctly without a C file and keeps the
        crate free of one, as flyology_cachelines is.

        Call numbers differ per architecture, and not only in value: the x86-64
        table and the table newer architectures share disagree on the order of
        get_mempolicy and set_mempolicy. Calling by a number from the wrong table
        reaches a working but unrelated kernel service, which is worse than not
        calling at all, so each table is written out separately and an architecture
        whose numbers are not recorded disables placement rather than borrowing
        them.

        That failure is silent by nature, so the host suite has an invariant that
        exposes it: a host that described its own memory nodes has the calls that
        act on them, so reporting no way to place memory means the calls were not
        reached. Building for one architecture with another's table was checked to
        fail on exactly that assertion rather than passing quietly, and passing a
        node set with a policy that takes none was checked to fail before the set
        was dropped.

        Verified on macOS aarch64, x86-64 Linux, and AArch64 Linux. macOS reports
        Unsupported_Host and places nothing. Both Linux architectures report
        Supported and complete every operation: every policy applied to a range and
        to the calling thread, a written page reported on an online node, an
        unaligned range refused, and an empty node set refused for a policy that
        needs one. Builds of the macos, linux and unsupported platform bodies across
        x86-64, AArch64 and an architecture with no recorded table emit no warnings,
        style diagnostics, or errors.

      11. 41e2d423
        Problem: Naming a memory node for an object means placing it by hand

        Flyology_NUMA.Placement acts on an address range. Using it to put an object
        on a chosen node means obtaining page-aligned memory, placing it, carving
        objects out of it, and releasing it afterwards, all in the caller's code and
        all outside the language's own way of saying where memory comes from.

        Ada already has that way: the storage pool of an access type. Nothing here
        supplied one.

        Solution: Add Flyology_NUMA.Pools, a storage pool whose subpools are nodes

        An access type names the pool and each allocation names the node, so where
        an object lives is written at the point it is created rather than arranged
        around it:

        Item : constant Sample_Access := new (On_Node (Arena, Near)) Sample'(...);

        Subpools are the part of the language that fits this. A pool alone would fix
        the node when the access type was declared; a subpool is chosen per
        allocation, which is what naming a node needs to be.

        The pool obtains whole pages from the host rather than taking memory from
        the ordinary heap. Heap memory may begin partway into a page whose remainder
        belongs to something else, and placing that page would move memory this
        crate does not own. Pages are placed before any of them is handed out, since
        placing them afterwards would leave whatever had already been written where
        the host first put it.

        Memory is handed out by advancing through pages already obtained, and goes
        back to the host when a subpool is deallocated or the pool is finalized.
        Freeing a single object does nothing. That suits memory built up and
        discarded together, which is what a node-bound arena usually is, and the
        interface says so rather than implying a general allocator.

        Ownership of the pages is left to the runtime's own teardown rather than
        taken over. The runtime keeps the records it needs to finalize an object
        inside the very pages that object lives in, and a pool that gave its pages
        back first would take those records with them; a pool holding anything with
        finalization would then fail on the way out of its own scope. Deallocating
        one subpool likewise forgets it, because the runtime has already detached it
        by then and a pool that still believed it owned it could never serve that
        node again.

        Only the policies that name a node can be given to a pool. The two that name
        none place nothing on the node the subpool stands for, so a pool built on
        one would report memory placed there that never was.

        Placement_Reached separates a host that placed the memory from one that
        could not, and says which of the two it means: the host accepted the
        request. Under a bound policy that puts the pages on the node; under a
        preferred one the host stays free to draw from elsewhere. Allocation
        succeeds either way, on the reasoning that memory in the wrong place still
        runs while no memory does not.

        A pool is not task safe, and the interface says so. Two tasks allocating
        from one subpool at once can be handed the same address.

        Verified on macOS aarch64, x86-64 Linux, and AArch64 Linux, and inside
        guests built to have several memory nodes, which no machine to hand does.
        scripts/multinode-check.sh boots a two-node guest and a four-node guest
        whose distances are uneven and one of whose nodes carries memory with no
        processor attached, then runs the host suite inside them. It was run on
        both x86-64 and AArch64, each emulating its own architecture, so that the
        placement calls a guest makes are the ones its architecture's table names. Those runs are
        what exercise choosing between nodes at all: memory bound to each node in
        turn and confirmed held by that node, including the node with no processor;
        interleaving spread over every node rather than drawn from one; and a node
        shown further from another than from itself.

        The suite gained cases for the two failures described above, and each was
        confirmed to fail before the change and pass after. Builds of the macos,
        linux and unsupported platform bodies across x86-64, AArch64 and an
        architecture with no recorded placement table emit no warnings, style
        diagnostics, or errors.

      12. a416d8dc
        Problem: The flyology_numa test entry point is not executable

        ./scripts/test.sh runs each crate's own entry point by path, so the file
        has to carry the executable bit. flyology_numa/scripts/test.sh was recorded
        without it and the whole suite stopped there, reporting only that a command
        could not be run.

        Running the script as an argument to a shell, which is what a person does
        while writing one, works either way and hides this.

        Solution: Record the executable bit, as the other crates' entry points do

      13. 550bc612
        Problem: flyology_numa is absent from the site and the API reference

        The crate ships, and nothing outside its own directory says so. It has no
        guide page, no generated API reference, and no entry in the library ledger
        or the machine-readable index. A reader who finds the other standalone
        crates on the site does not find this one.

        Solution: Adopt the crate into the documentation and the site

        The crate now builds its own GNATdoc reference, and the root documentation
        run builds and asserts it alongside the other crates. Publishing it required
        documenting the pool primitives the runtime calls, which had no comments,
        and describing the pool's discriminants in prose: @field names a record
        component, and a discriminant of a private type is neither.

        The package renaming that shortened System.Storage_Pools.Subpools in the
        public part is now in the private part. GNATdoc reported the public renaming
        on every documentation run, and the full name appears twice in the visible
        declarations rather than in every generated page.

        The guide page follows the order a reader needs: add the crate, read the
        node structure, use the permitted nodes rather than the online ones, handle
        a host with one memory domain, place memory, allocate from a node, and read
        distances and packages for what they say rather than what they suggest.

        Every API link on that page was resolved through the generated search index
        rather than by reading the generated markup, which does not put an entity's
        name where a reader of the HTML would expect it.

        The library ledger keeps its alphabetical order, so the new entry is S05 and
        the two entries after it move up.

        Verified with ./scripts/docs.sh, which builds the reference with no
        undocumented-entity warnings, and ./scripts/build-site.sh followed by the
        site checker, which reports 144 HTML files and 201 total files. The crate's
        own suite still passes.

      14. ae1e3ddf
        Problem: The landing page does not list flyology_numa

        The project map in the hero names each standalone library, and the
        catalogue below it links each one. Both lists stop at the crates that
        existed before this one. A reader who arrives at the site and looks for what
        Flyology offers does not learn that the crate exists.

        Solution: Add the crate to the hero project map and the catalogue

        Both lists keep their alphabetical order, so the entry sits between IRI and
        SIMD. The catalogue entry links to the guide, as the entries for the other
        crates with a guide on this site do.

        Verified with ./scripts/build-site.sh and the site checker, and by fetching
        the built pages: the hero and catalogue both list the crate, and all 39
        internal links on its guide page resolve.

      15. aa8b12ed
        Problem: The numa guide explains how before it explains what

        The page opens with a short definition in a callout and then goes straight
        to adding the crate. A reader who does not already know what a memory node
        is learns the interface before the reason for it, and a reader who does know
        still gets no picture of the machine the crate describes.

        Solution: Open with a section that explains memory nodes and draws one

        The section states what changes when a machine has more than one processor
        package, draws a two-node machine with a local and a remote access, and says
        plainly when placement is worth doing at all: a program that fits in cache,
        or one that allocates little, does not gain from it. The callout it replaces
        said less.

        The diagram uses only the classes the figure context defines. An earlier
        draft used a class that context does not style, and SVG then fell back to a
        solid black fill. That reads as deliberate against a dark background and
        wrong against a light one, which is how it survived a first look.

        Both themes were checked by computed style rather than by eye. The
        containers take the page's own surface and border colours, so they follow
        the theme instead of fighting it.

        Verified with ./scripts/build-site.sh and the site checker.

      16. 7b70cbf6
        Problem: Allocation algorithms are coupled to Flyology shared-memory policy

        Buddy, best-fit, and TLSF live inside the main package hierarchy, so bare-board runtimes cannot reuse them without also accepting Flyology identity, mapping, and shared-memory concerns.

        Solution: Extract allocation algorithms into a standalone crate

        Add flyology_allocators 0.1.0-dev with caller-owned regions, timed contention retries, native and ARM bare-board verification, and optimized memory primitives. Keep magic and schema policy in a thin Flyology adapter, pin the new crate from Flyology, and update integration tests and documentation.

      17. 7bf86246
        Problem: Standalone allocator performance has no focused comparison

        The extracted algorithms lack a reproducible benchmark against the platform allocator, making hot-path regressions and algorithm tradeoffs difficult to measure.

        Solution: Add a dedicated flyology_bench allocator shootout

        Add an optional hosted benchmark subcrate with fixed-size and fragmented-churn workloads comparing malloc, Buddy, Best-Fit, and TLSF in balanced paired rounds. Keep benchmark dependencies outside the bare-board crate closure and document release and smoke workflows.

      18. be44ac54
        Problem: Buddy allocator repeats checked address work on every node

        Profiling shows recursive Buddy allocation and release spend most of their time rebuilding and validating structure-relative node addresses. Release also validates each handle twice before its first mutation, making small allocation cycles substantially slower than the other standalone algorithms.

        Solution: Cache the validated Buddy node-table binding

        Retain the process-local node-table base in the attached view after validating its complete native range, use bounded node-relative addressing on hot paths, clear the binding on detach, and remove the redundant release validation while preserving validation before mutation.

      19. 283d5e71
        Problem: TLSF repeats checked address work on every metadata field

        Profiles of fixed allocation cycles show TLSF spending most of its time in free-list insertion and removal, block initialization, and handle validation. Each logical operation repeatedly recomputes and validates the same block base before touching adjacent scalar fields, leaving the constant-time algorithm dominated by address machinery.

        Solution: Reuse validated block bases across TLSF hot paths

        Validate each referenced block extent once, carry its process-local base through list mutation, splitting, coalescing, and handle release, and keep stored link, size, generation, state, and bitmap checks intact. Avoid a redundant ready-state check while the arena guard is held and replace size-class division by its exact power-of-two shift.

      20. e9199d66
        Problem: Best-fit allocator repeats metadata work on hot paths

        Profiling shows fixed-layout address validation, duplicate split and coalesce writes, and repeated AVL balance reads dominate Best-Fit allocation and release. This leaves both fixed cycles and fragmented churn substantially slower than necessary.

        Solution: Streamline checked Best-Fit metadata operations

        Cache the last complete block-header location in the local view, use a fixed-field address path that retains attachment and complete-header bounds checks, avoid tree metadata writes that insertion immediately replaces, and compute AVL balance inputs once per ancestor. The stored layout, persisted validation, guard behavior, handle generations, and bare-board dependency boundary remain unchanged.

      21. 05d2eb83
        Problem: Allocator benchmarks leave imported algorithms unoptimized

        The benchmark project selects release switches only for its own sources. Imported flyology_allocators units are compiled without optimization, making comparisons against the optimized system malloc misleading and overstating allocator hot-path costs.

        Solution: Force a clean optimized benchmark closure

        Build the benchmark and all imported Ada sources through gprbuild with explicit O3, debug symbols, Ada 2022, warnings, and validity checks. Document why the runner must apply switches across project boundaries.

      22. 77e1d163
        Problem: Benchmark arrays use obsolete aggregate syntax

        GNAT reports parenthesized array aggregates as obsolescent when the benchmark closure is compiled as Ada 2022, obscuring useful build diagnostics.

        Solution: Adopt Ada 2022 bracketed array aggregates

        Convert Flyology Bench array initializers and expressions to bracket syntax while retaining parentheses for record aggregates. Keep the obsolescent warning category enabled so future occurrences remain visible.

      23. 77ce4c04
        Problem: TLSF eagerly coalesces every released block

        Release repeatedly discovers physical neighbors and removes and reinserts free-list entries even when the next allocation can reuse the same size class. This makes steady fixed-size and churn workloads pay fragmentation-recovery costs on every operation.

        Solution: Defer TLSF coalescing until allocation requires it

        Return released blocks directly to their size class and perform a bounded, checked physical coalescing pass only after a normal TLSF search misses or before destroying an empty arena. Preserve boundary tags and bitmap/list validation, and cover adjacent runs, allocated gaps, attachment, stale handles, and complete teardown with adversarial tests.

      24. 562bdd61
        Problem: TLSF still advertises eager constant-bound behavior

        Lazy coalescing makes worst-case allocation linear and no longer joins neighbors during release, but both capability records and package comments retain the eager algorithm contract. Flyology also reuses the eager persisted identity even though version 2 readers reject valid adjacent free blocks produced by the new implementation.

        Solution: Publish the lazy TLSF contract and identity

        Report the linear worst-case search and deferred release coalescing in standalone and Flyology packages, document the miss-triggered pass, and advance Flyology TLSF to version/schema 3 so cross-version attachment fails at the immutable header. Add standalone capability coverage and a Flyology regression that rejects the complete eager identity.

      25. 288b03a2
        Problem: Best-fit repeats split and merge work on exact reuse

        Profiling shows fixed-size allocation cycles spend most of their Best-Fit time splitting a large free block during allocation and immediately removing and coalescing its remainder during release. Fragmented churn repeats related AVL maintenance even when the same physical block can be reused directly.

        Solution: Defer Best-Fit coalescing until allocation needs it

        Index released blocks directly for exact-size reuse. Before reporting exhaustion, validate the complete physical chain, coalesce every adjacent free run, repair boundary links, and retry the AVL search. Accept the resulting persisted representation on attachment, canonicalize empty arenas during destruction, report the resulting linear worst-case search capability, and cover adjacent frees, alternating gaps, stale handles, attachment validation, and teardown.

      26. 41578832
        Problem: Flyology Best-Fit identity permits incompatible lazy images

        Deferred coalescing leaves adjacent free blocks as a valid persisted Best-Fit state. The earlier eager reader rejects that state, but Flyology still advertises the same outer version and schema, so compatibility fails only after entering nested allocator validation.

        Solution: Version the Flyology Best-Fit lazy invariant

        Advance the Flyology-only adapter version and schema while retaining its magic. This makes older readers reject lazy images at the outer identity boundary and keeps standalone allocator metadata free of application identity.

      27. ec813587
        Problem: Best-Fit identity transition lacks Flyology coverage

        The lazy Best-Fit adapter advances its persisted version and schema, but the Flyology data-structure smoke test neither proves rejection of the eager version-2 identity nor reflects the linear fallback and deferred-coalescing capabilities.

        Solution: Exercise the Best-Fit version-3 boundary

        Temporarily replace a live Best-Fit arena outer identity with the version-2 values and require attachment to fail closed, then restore the image. Assert the truthful lazy-coalescing capabilities for both Best-Fit and TLSF.

      28. e1315591
        Problem: Buddy eagerly rebuilds the same free hierarchy

        Small allocation cycles repeatedly collapse a released leaf to the root and split the same path on the next allocation. Profiling shows those release stores and recursive rebuilding dominate Buddy's fixed-size cost.

        Solution: Coalesce Buddy trees only when allocation needs it

        Keep released nodes in the retained split tree, compact free subtrees before a search reports genuine exhaustion, and compact before empty-arena destruction. Add adversarial coverage for half-tree and root reconstruction plus stale handles, and expose the lazy-coalescing capability accurately.

      29. 4ad89a24
        Problem: Lazy Buddy reuse still traverses the retained tree

        After deferring coalescing, profiling shows fixed-size Buddy allocation is dominated by walking the same split path. Fragmented churn also revisits released orders even though the releasing view already knows a suitable free node.

        Solution: Cache one validated free node per Buddy order

        Keep process-local node hints in each attached view, validate persisted state before every hinted reuse, and discard all hints during coalescing and detach. Preserve the persisted layout and fall back to the complete tree for stale or missing hints; cover stale hints across independently attached views.

      30. 22998f64
        Problem: Lazy Buddy metadata boundaries are incomplete

        Buddy still advertises logarithmic eager-coalescing behavior, an eager Flyology reader can attach a retained all-free split tree and falsely report exhaustion for a parent-sized request, and Destroy may release its guard after a partially failed coalescing pass without poisoning the image.

        Solution: Harden lazy Buddy capabilities and lifecycle handling

        Advertise linear miss search and deferred coalescing, advance only Flyology's outer Buddy identity to version 3, and verify the retained two-leaf compatibility case. Check that an arena is empty before Destroy mutates it and poison any coalescing failure. Compile the standalone project as Ada 2022 for bracket aggregates and extend standalone and Flyology compatibility tests.

      31. 66888189
        Problem: Allocator guides still describe eager coalescing

        Buddy, Best-Fit, and TLSF now defer coalescing until an allocation miss, but the root, standalone, and website guides still advertise their former fast-path and worst-case behavior. The stale prose also describes a process-shared guard even though the standalone algorithms are usable with arbitrary caller-owned storage.

        Solution: Document lazy coalescing and view-scoped state

        Describe each successful lookup and miss-triggered coalescing path, report the resulting linear worst-case bound, and use attached-view terminology. Record that stored geometry remains stable while the valid state contract changes and Flyology adapters use version-3 identities.

      32. 94cd5b57
        Problem: Lazy allocator correctness lacks an executable model

        Buddy, Best-Fit, and TLSF now retain free structure on release and coalesce on allocation misses. Behavioral tests cover examples, but no bounded state-machine review checks shared guard ownership, block partitions, index publication, stale view hints, generation-stamped release, false exhaustion, or operation completion across interleavings.

        Solution: Model guarded allocator transitions in TLA+

        Add a parameterized extraction for the three algorithms with policy-specific splitting and selection, TLSF bin and bitmap state, Buddy view-local hints, lazy coalescing, retry, generations, and fairness. Add safe TLC configurations plus required false-exhaustion, stale-hint, stale-bitmap, stale-release, and nontermination counterexamples, wire them into the authoritative runner, and document the production mapping and abstraction limits.

      33. 4dc3e5c0
        Problem: Allocator models can drift from Ada transitions

        The bounded Buddy, Best-Fit, and TLSF models establish safety and liveness for their extraction, but review alone does not detect when persisted metadata, view-local hints, generations, handles, or size-class computations diverge from the standalone kernels.

        Solution: Compare canonical Ada and TLC allocator traces

        Add test-only private-state observers and bounded public-operation traces for all three kernels. Model the same traces in TLA+, compare every operation-boundary snapshot byte-for-byte in the authoritative runner, require no-retry liveness counterexamples, and run the conformance boundary in CI while retaining standalone ARM cross-build isolation.

      34. 54d77f0f
        Problem: allocators lack a slab and span policy

        Solution: add a standalone bitmap-slab and contiguous-span allocator, bridge it into Flyology, benchmark it against the existing policies and malloc, and cover its bounded state machine with positive and deliberately broken TLA+ configurations.

      35. 239aa004
        Problem: slab slot reuse lacks a publication edge

        Solution: publish the affected 32-bit bitmap word with release ordering and acquire it before validating the slot generation. Add bounded safe and deliberately broken TLA+ visibility models so TLC reproduces the former stale-handle acceptance.

      36. 195b83bf
        Problem: large span validation trusts the head extent

        Solution: add a corruption test that makes one large-span head claim its neighboring live allocation, then validate every head and tail descriptor field before reporting capacity or allowing release to mutate the claimed extent.

      37. 7a7bc16f
        Problem: The site does not list flyology_allocators

        The hero project map, the standalone catalogue, the library ledger, and
        llms.txt each name every standalone crate. This branch adds a new one, and
        all four lists stop at the crates that existed when the branch was written.
        A reader who arrives at the site and looks for what Flyology offers does not
        learn that the crate exists.

        Solution: Add the crate to the hero map, catalogue, ledger, and llms.txt

        Every list keeps its alphabetical order, so the entry sits first among the
        standalone crates and the ledger indices shift from S01..S07 to S02..S08.

        The crate publishes neither a guide page on this site nor a generated API,
        because scripts/docs.sh does not build one and flyology.gpr excludes the
        crate from documentation. The entries therefore link to the source tree
        only, as the Flyology QUIC entry already does for the same reason. Adding an
        api/flyology_allocators/ link would fail the site checker.

        Verified with ./scripts/build-site.sh and the site checker, which passes on
        141 HTML files, and by grepping the built pages: the hero, catalogue,
        ledger, and llms.txt all name the crate.

      38. 7dc419f2
        Problem: The data-structures guide links to pages GNATdoc no longer emits

        This branch turns Allocation_Algorithms.Buddy, Best_Fit, and TLSF from
        documented packages into generic instantiations of Allocation_Algorithms
        .Contract. GNATdoc emits no unit page and no declaration anchor for an
        instantiation, so the three API links the guide carries for them now resolve
        to nothing. main gained a site link checker after this branch was written,
        so the Pages workflow reports all three and fails.

        Solution: Present the three instantiations as code rather than links

        AGENTS.md asks that the first explanatory mention of a public entity link to
        its verified generated GNATdoc unit or declaration entry. No entry is
        generated for these three, so there is nothing to link, and pointing them at
        the kernels or at Contract would name a different entity than the prose
        does. The surrounding Arenas, Contract, Allocation_Capabilities, and View
        links are unaffected and still resolve.

        Verified with ./scripts/build-site.sh and the site checker, which now passes
        on 141 HTML files and 198 total files with zero problems.

      39. 9a24bf68
        Problem: The data-structures guide omits the slab/span allocator

        This branch adds Allocation_Algorithms.Slab_Span as a fourth arena allocator
        and says so in the README, but the guide section that tells a reader how to
        choose one still presents three. It names three adapters, describes three
        policies, gives three decision rows, and twice states that all three share
        one metadata guard. A reader choosing an allocator from this page does not
        learn the fourth exists, and the two counts now contradict the README.

        Solution: Describe slab/span alongside the other three and correct the counts

        The introductory paragraph names the adapter and states its shape: bitmap
        slots in fixed runs for small requests, contiguous runs for larger ones, with
        descriptors and generation tables outside the managed bytes. A decision row
        gives the selection rule and the reclamation behavior a caller can observe:
        requests up to half the configured run size take a generation-stamped slot,
        larger requests reserve whole runs, release keeps an emptied slab indexed for
        reuse, and a miss reclaims empty slabs to obtain the run or span it needs.

        The row also states that the run size is an allocator quantum rather than an
        operating-system page, because the name invites the opposite assumption.

        The half-run threshold matches the kernel, which sends a request to a slab
        class when Requested <= Run_Size / 2 and to a span otherwise. Both "all
        three" counts become four. The adapter is a generic instantiation, so like
        Buddy, Best_Fit, and TLSF it has no generated GNATdoc entry to link.

        Verified with ./scripts/build-site.sh and the site checker, which passes on
        141 HTML files and 198 total files, and by parsing the built page: tags
        balance and the new row renders between TLSF and the compile-time choice.

    2. 9a24bf68 updated to 60de2c69index 8a8e9de5

      1 source commit

      1. 60de2c69
        Problem: A development pin ships in the published manifest

        flyology.gpr imports flyology_allocators.gpr, and the manifest both declares
        flyology_allocators as a dependency and pins it to the in-repo directory.
        Alire honours pins only in a root crate's manifest, so a consumer resolving
        flyology from the index never receives that dependency. Its solution omits
        flyology_allocators entirely and gprbuild then fails with "imported project
        file flyology_allocators.gpr not found". A crate whose only dependency is
        flyology = "~0.1.1-dev" reproduces it in two lines.

        Nothing in this repository reports the fault, because the pin satisfies the
        dependency for every build performed here. The pin also hid two further
        assumptions that only the in-repo directory could satisfy.

        Solution: Resolve the allocators dependency from the index

        Drop the pin so the declared dependency resolves the same way for this crate
        and for its consumers. The published flyology_allocators 0.1.0-dev is built
        from this repository at the same commit and the same subdirectory, so the
        source reached is identical; only the path by which it is reached changes.

        Configure the organization index in this repository's own workflows. They
        carried the community index alone, because the pin meant no job here ever
        resolved flyology_allocators from an index, and it is published only in the
        organization index. Without that step alr reports an incomplete solution
        naming flyology_allocators as missing.

        Name the excluded documentation project through the imported project rather
        than through a repository path. Documentation.Excluded_Project_Files listed
        flyology_allocators/flyology_allocators.gpr, which resolved only while the
        crate sat in this working tree; as a dependency its project lives in the
        Alire build tree under a content hash. Flyology_Allocators'Project_Dir asks
        the imported project where it is, so the exclusion holds wherever the
        dependency is deployed and the allocator packages stay out of this crate's
        generated API, where they would otherwise be documented twice.

        Record the rule that produced the fault in the agent guide: no committed
        pins in a crate manifest, alr pin in the consuming workspace for unpublished
        work, and a declared dependency must resolve from the index. Name the
        gprbuild error there too, since that is where the fault appears and it names
        a project file rather than a crate.

    3. 60de2c69 updated to 9782c81bindex 75a836be

      16 source commits

      1. aeb10612
        Problem: The site does not list Flyology RDF

        The hero project map, the standalone catalogue, the library ledger, and
        llms.txt each name every component. Flyology RDF publishes a website, a
        guide, and three generated API references at rdf.flyology.org, but the name
        appears nowhere in this repository. A reader who arrives at the site and
        looks for what Flyology offers does not learn that the project exists.

        Solution: Add the project to the hero map, catalogue, ledger, and llms.txt

        flyology_rdf depends on flyology_iri only. It needs no runtime preparation
        and starts no tasks, so it belongs with the standalone libraries. Every list
        keeps its alphabetical order, so the entry sits between Flyology NUMA and
        Flyology SIMD and the ledger indices shift from S07..S08 to S08..S09.

        The ledger and llms.txt entries carry all three generated references, as the
        Flyology Postgres entries already do, because the project site treats the
        Notation3 and SPARQL APIs as first-class navigation.

        The llms.txt project-structure summary also omitted Flyology Allocators and
        Flyology NUMA, which the same file already listed further down. Both names
        join the summary here.

        Verified with the website-kit site checker, whose output is unchanged from
        the pre-change baseline, and by rendering the pages: the hero, catalogue,
        and ledger all name the project. The six linked URLs return 200.

      2. 2188ee0d
        Problem: The project map announces its framing and then hides the components

        The figure caption claimed "One project, two adoption paths" above two cards
        that already carry the same fact in their labels, so the caption restated
        what the diagram shows. The two card subtitles were not parallel either:
        "Core component" named a role while "No runtime dependency" named a
        dependency, so neither pair member helped a reader compare the paths.

        The component names below them were plain list items. A reader who found the
        name that matched the problem had no way to reach the component from the
        diagram and had to scroll to the catalogue to find the same name again.

        Solution: Drop the caption, make the subtitles parallel, and link the names

        The subtitles now read "Prepare the runtime" and "Add a crate", which state
        the two adoption paths as the actions they are. The figure keeps an
        accessible name through aria-label, and the figcaption rule leaves the
        stylesheet with the element it styled.

        Each component name becomes a link to its best available destination, which
        is the destination the catalogue below already uses: the project site where
        one exists, then the guide, then the generated API, then the source tree.
        The pill moves from the list item to the anchor so the whole badge is the
        hit target. Links open in a new tab and carry no underline, as requested, so
        hover brightens the border and adds a faint fill instead. Each list states
        the new-tab behavior once in its aria-label rather than repeating it in
        twelve hidden spans.

        Verified by rendering the page: every badge computes text-decoration-line
        none and cursor pointer, and the hovered badge is distinguishable from its
        neighbors. The site checker reports one new line against the baseline,
        api/flyology_debug/ from the new Debug badge, which resolves once
        scripts/docs.sh generates the GNATdoc output that this partial build omits.

      3. 5dfd5d36
        Problem: Nothing coordinates tools that need exclusive CPU capacity

        Two measurement runs that share a machine produce two wrong answers, and
        neither run can tell that it happened. The problem is not confined to
        benchmarks: a load generator, a soak test, or a profiler makes the machine
        loud, and a benchmark needs it quiet. Both want the same thing from opposite
        directions, and nothing lets them find each other.

        Worse, two runs that each suspend collection when they detect interference
        are symmetric controllers observing each other. Each pauses because the other
        is loading the machine, both then observe quiet, both resume together, and
        both immediately pause again.

        Solution: Specify a host CPU lock convention and implement it

        The convention is named for the resource rather than for benchmarking, so
        that the tools which create load take the same claim as the tools which need
        its absence. Conflict detection is flock and nothing else: liveness is the
        lock itself, so a holder that dies releases with no cleanup path, no stale
        registry entries, and no pid-reuse hazard.

        A machine-wide claim takes LOCK_EX on the claim file; a claim on individual
        CPUs takes LOCK_SH there and LOCK_EX on one file per CPU. Disjoint core-scoped
        claims therefore proceed concurrently while a machine-wide claim excludes them
        all, with no registry and no arbiter. Per-CPU claims are acquired in ascending
        order, because a total order is what stops two callers with overlapping sets
        from deadlocking on each other's partial claims.

        The path is a single deterministic default rather than a writability-probing
        fallback chain. A chain reintroduces the failure it was meant to prevent:
        /run/lock is 1777 on Debian and root-owned 0755 on Red Hat derivatives, so a
        root process and an unprivileged process on one machine would probe
        differently, land on different files, and each conclude it holds the machine.
        $TMPDIR is avoided for the same reason, being per-user on macOS.

        File content is diagnostic and is never consulted to decide conflicts. It is
        still specified and parseable, one key=value pair per line, because a reader
        must be able to name the holder; cwd is included because tool and pid alone do
        not distinguish one checkout or CI workspace from another. Readers open the
        file without locking, since a shared lock would block behind the very holder
        they are trying to identify, and must tolerate content that is empty, stale,
        or half-written.

        A claim is not proof of exclusivity, and the implementation does not present
        it as one. systemd PrivateTmp= bind-mounts a per-service directory over /tmp,
        so two services share every CPU and cannot see each other's claim files; that
        case is detected from /proc/self/mountinfo and reported as namespace-scoped.
        Separate containers are not detectable from inside and need an explicit shared
        path. A path can be proven private but never proven machine-wide.

        Only the C macros live in the native unit. GNAT's C_Variadic_2 convention
        calls open() correctly even on Darwin/AArch64, where variadic arguments are
        passed differently from fixed ones, so the protocol, the file grammar, and the
        /proc reader are all Ada. The convention compiles on every GNAT this crate
        supports, checked against 13.2.2 through 16.1.0 against an alire.toml floor of
        13, so no compatibility shim is carried.

        Verified by building the crate, and by taking claims on disk: the file matches
        the published grammar, parses with awk -F=, is created 0666, and per-CPU files
        are named beside the machine file.

      4. 13b71a5b
        Problem: The CPU gate only proves the host was quiet before warmup

        CPU_Quiescence samples host counters once, before clock characterization, and
        then never looks again. A machine that goes busy halfway through collection
        produces a result that reads as clean, and nothing in the measurement, the
        console card, or the machine-readable output says otherwise. The gate's own
        documentation admits it "cannot prevent new load from arriving after
        collection begins", and until now that was the end of the story.

        The obvious repair is not available either. Host utilization cannot simply be
        compared against a limit during collection the way the preflight does it,
        because by then the benchmark thread saturates a core and every sample would
        trip the limit.

        Solution: Watch for foreign load during collection and say what was found

        Foreign load is host busy time minus this process's own CPU time, so load the
        benchmark itself creates is correctly not foreign. The estimate scales the
        host busy ratio by wall time rather than converting ticks, so the platform
        tick length never enters the arithmetic. Cross-checked against top on a loaded
        machine, the two agree to within 0.1 percent.

        Three responses form a ladder. Observe records and keeps everything. Retake
        discards the contaminated window and collects it again. Pause waits for the
        host to settle, re-warms, and then collects it again. The re-warm is not
        politeness: a resumed run has cold caches, predictors, and frequency state, so
        without it the first sample after a pause is the outlier the pause existed to
        avoid.

        Nothing adjusts a reported statistic. A skew factor derived from observed load
        would be invented data, because the cost of interference depends on whether
        the contention is an SMT sibling, a shared cache, memory bandwidth, or another
        socket, and the same foreign share can mean no slowdown or a large one. Runs
        are annotated or repaired, never corrected.

        Observation happens between timed samples over windows of whole collection
        units, where a unit is one sample, one comparison pair, or one balanced
        multi-way round. A response therefore never splits the two halves of a pair
        and never lands mid-round, where it would spread interference unevenly across
        the cases a round exists to compare fairly. Windows carry a margin over the
        configured minimum: sized to only just reach it, ordinary batch jitter drops
        them below it and they silently degrade to observation. Host counters are
        tick-based, so a window that still falls short is recorded but never acted on.

        Discarding a window rolls back what the window changed. Per-sample values are
        written by index and survive a retake intact, but the position tally of a
        comparison pair and the process-telemetry summaries are running sums, so a
        discarded pass gives them back. Without that, a run with eighteen retained
        samples and twenty-four retakes would report elapsed time and an average CPU
        share covering forty-two samples, most of which were thrown away.

        Budgets degrade rather than abort. An exhausted retake or pause budget
        continues under Observe and reports it, and paused time is excluded from
        Maximum_Sampling_Time because waiting for the host is not collection.

        Placement is optional and sharpens attribution: with a strict binding every
        other CPU's busy time is foreign outright, and the placed CPU's share is its
        busy time minus the placed thread's own. SMT siblings join the watched set,
        because a process saturating the sibling of the placed CPU slows the
        measurement while leaving the placed CPU's own share clean, which makes
        sibling-blind core-scoped observation worse than host-wide observation rather
        than better. Placement is Linux-only in practice; Apple Silicon implements no
        thread affinity and rejects every request, so the Host_Control documentation
        no longer describes Darwin placement as merely advisory.

        Placement binds only the calling thread, so another thread of this process can
        occupy a watched CPU, where its time is indistinguishable from foreign load.
        Each window therefore reads process CPU as well as thread CPU, and their
        difference bounds how much of the watched capacity those threads could account
        for. Once that bound exceeds the configured foreign limit, the core-scoped
        answer can no longer address the question the limit asks: the run drops to
        host-wide observation, which is well defined for a multi-threaded process, and
        reports Attribution_Diluted. Otherwise a scheduler benchmark run under
        placement would spend its retake budget discarding samples over load it
        created itself. The window that reveals the dilution is discarded rather than
        recorded, because its value was computed under the attribution being
        abandoned.

        The direction of that fallback is deliberate. Core-scoped attribution
        subtracts only the placed thread, which over-reports interference when other
        threads share the watched CPUs; subtracting the whole process instead would
        deduct time our threads spent on CPUs outside the watched set, under-report
        foreign load, and let contaminated data pass as clean. Over-reporting shows up
        in the retake and contamination counts; under-reporting shows up nowhere.

        The host CPU claim is taken before the preflight gate, since waiting for a
        quiet host and then blocking on the claim leaves the quiet verdict stale.

        Everything observed reaches the console card, the CSV schema, and the JSON
        object. That visibility is the point: a run that had to repair itself must say
        so, or a heavily repaired result reads as a quieter machine than the one it
        ran on.

        Verified with ./scripts/test.sh on Darwin/aarch64 and in an Ubuntu 24.04
        container on Linux/aarch64, and under qemu-system-aarch64 across four CPU
        topologies. Core-scoped attribution asserts that it closed an observation
        window, so the thread-CPU probe it depends on cannot fail silently. Two
        assertions were checked against builds that defeat them: one with sibling
        collection disabled fails the sibling assertion under cores=2,threads=2 and
        passes without SMT, and one with the dilution check disabled fails the
        fallback assertion while a task of the test's own process burns CPU. Retake
        and pause are driven by a spawned process, because load raised inside this
        process is its own CPU time and is subtracted by design.

      5. 845bdaca
        Problem: The new guide section ignores the site's writing rules

        website/AGENTS.md governs hand-written pages under guide/**. The interference
        section met none of its API-link requirements and several of its style rules.

        Every public entity it introduced went unlinked: Interference, Placement,
        Host_Lock, the three Interference_Response literals, Maximum_Retakes, Window,
        Rewarm_Time, Maximum_Foreign_CPU_Percent, Include_Siblings, Require_Strict,
        Attribution_Diluted, and Environment. The same page already links
        CPU_Quiescence, Stable_Time, and Timeout, so the new section also read
        inconsistently against its own neighbours.

        Solution: Link the API entities and apply the three prescribed reviews

        The three reviews ran in sequence and are labelled here, since separate review
        agents were unavailable.

        Technical. "Foreign load is host busy time minus this process's own CPU time"
        held only without placement, because core-scoped attribution subtracts the
        placed thread rather than the whole process; the sentence now says so, and the
        placement paragraph states which CPUs the harness measures. "The re-warm is
        required" overstated a configurable field, so the text names Rewarm_Time and
        says what a zero value leaves behind. "When the difference exceeds the
        configured limit" named neither the limit nor the compared quantity, which
        also left Maximum_Foreign_CPU_Percent unlinked. Two harnesses that both pause
        do not deadlock as claimed; they alternate between pausing and resuming.

        Editorial. "This matters most" and "Without it" both referred back to
        something unnamed. Both now name their subject.

        Controlled language. "Sharpens attribution" was figurative and is now
        "narrows attribution to the placed CPU and its SMT siblings". "A run that
        repaired itself reports that fact" personified the run; the report is the
        actor, and it states counts.

        Verified with ./scripts/build-site.sh and the site checker, which passes 144
        HTML files. All fourteen API links resolve to an existing anchor in the
        generated GNATdoc output, and each target matches the entry the API search
        index gives for that entity. No sentence in the section exceeds the 25-word
        review signal.

      6. edf788ef
        Problem: The guide does not say the host controls are opt-in

        The interference section described three capabilities without saying that a
        run acquires none of them unless it asks. BENCH 07 states that contract for
        the preflight gate, and the page marks the default value of a choice where one
        exists, as it does for Equal_Time and Balanced_Rounds. The new section did
        neither, so a reader could not tell that enabling the watch alone changes
        nothing about the collected data.

        The claim file was also absent. The page named three environment variables but
        not the one path that other tools must agree on, leaving the coordination
        surface a click away in the convention document.

        Solution: State the defaults, the claim path, and the budget interaction

        Observe is now marked as the default response, in the form the page already
        uses. The closing paragraph mirrors BENCH 07: the watch, placement, and the
        host claim are disabled by default, so an existing run acquires no new wait or
        failure condition. The opening sentence calls the watch optional where the
        reader first meets it.

        The claim paragraph names /tmp/host-cpu.lock, the Path field that overrides it
        for one run, and the HOST_CPU_LOCK_PATH variable that overrides it for every
        tool following the convention. An earlier draft named only the variable, which
        implied it was the sole override; the technical review caught that against
        Resolved_Path and Try_Acquire.

        The Window row gains the limit that qualifies it. A window covers whole units,
        so a window spanning many short samples can exceed Maximum_Retakes on its
        first discard. Collection then continues under Observe and reports the
        exhausted budget, which otherwise looks like the response never ran.

        Numeric field defaults are deliberately not repeated here. No other section of
        the page tabulates them, every field now links to its generated entry, and a
        duplicated value is one that can go stale.

        Verified with ./scripts/build-site.sh and the site checker, which passes 144
        HTML files. All fifteen API links resolve to an existing anchor, and each
        target matches the entry the API search index gives for that entity, including
        the ambiguous Path simple name, which resolves to Host_Lock_Policy.Path. No
        sentence in the section exceeds the 25-word review signal, and no entity is
        linked twice.

      7. 4fbe5020
        Problem: The recording smoke test separates its workloads with a delay

        recording_smoke drives two benchmarks from four tasks and asserts that the
        slow benchmark's recorded median wall time exceeds the fast one's. The
        separation comes from delay 0.000_2 against delay 0.000_8. A relative delay
        is rounded up to the host timer tick, and on a Linux kernel with a coarse
        tick both requests wake at the same boundary near 3 ms. A four-task probe
        with no recorder involved shows the first iteration of each task honoring
        the request and every later one landing on the same plateau:

        0.0002 s: 323 3710 2829 2972 3069 2947 ... (us)
        0.0008 s: 1167 3307 2482 3625 2793 3045 ... (us)

        The two recorded medians then arrive at 2.98 ms and 2.99 ms, ordered by
        scheduling noise alone. On Ubuntu 24.04 with GNAT 16.1.0 on aarch64 the
        assertion fails about half the time: 9 of 20 runs on a clean checkout. macOS
        resolves the two delays apart, which is why the test has held there. The
        independent comparison checked two assertions below rests on the same
        separation and fails with it.

        Solution: Separate the distributions by work the workers perform

        Each worker spins a volatile rotate-and-xor accumulator, 20_000 rounds for
        the fast benchmark and twenty times that for the slow one, the idiom the
        file's concurrent PMU-session block already uses. That is roughly 33 us
        against 680 us, a twentyfold gap read by a nanosecond wall clock, so no
        timer resolution enters the measurement. It also costs less than the
        sleeping it replaces: the slow workers take about 14 ms rather than 60 ms.

        The assertion stands, since the ordering is the invariant worth holding, but
        its message now carries both medians so a failure on an unusual host reports
        numbers rather than a verdict.

        Verified on the failing environment, an Ubuntu 24.04 container with GNAT
        16.1.0 on aarch64: 30 of 30 runs pass where HEAD fails 9 of 20 in the same
        container, 20 of 20 under a two-CPU quota, and 10 of 10 with 24 competing
        spinners on that quota. scripts/test.sh passes three times from a fresh
        source export there and once on macOS. A calibration probe over 105 further
        trials across those CPU configurations held the ratio between 14x and 30x
        with no inversions and Relative_Change_Percent positive throughout.

      8. ae5b52d7
        Problem: A group snapshot cannot say whether its event loop is busy

        Flyology.Observability.Group_Snapshot carries thirty fields covering queue
        depths, wait categories, and cumulative counters, but none of them reports how
        much of an event loop's time was spent doing work. Pool imbalance is therefore
        invisible from outside the process: a group with a deep ready queue and a group
        that is idle produce the same evidence once their momentary queue depths match.
        Made_Progress detects a stalled loop but not a saturated one, and its comment
        already records why a per-dispatch clock read was rejected as the answer.

        Solution: Time the poller wait a loop takes when nothing is ready

        An event loop enters Wait_Batch only when its ready queue is empty, so the idle
        path is both the exact complement of the loop's working time and a path a busy
        loop never repeats. The scheduler stamps the wait before releasing the group
        lock and closes it after reacquiring, keeping the in-progress wait in the group
        so an observer adds it rather than charging a long block as busy time. Nothing
        is added to dispatch, context switch, or any other hot path.

        Group_Snapshot gains Uptime_Nanoseconds, Idle_Nanoseconds, and Idle_Waits, and
        the runtime snapshot ABI moves to version 6. Idle time is clamped to uptime and
        both come from one clock reading, so callers can always take the difference or
        the ratio. tests/native/process_lifecycle_probe.c pins that ABI and its layout,
        and moves with it.

        The cost is measured rather than asserted. runtime_callback_bench adds
        poller_idle_cycle for the instrumented path and monotonic_clock_read for the
        unit of work it adds; benchmarks/idle_wait_rate reports the rate a loop
        actually reaches, because the effect is far below what a differential timing
        run resolves on this host. On macOS/AArch64 a reading costs about 20 ns, a
        socket ping-pong reaches roughly 32,000 to 38,000 waits per second per loop,
        and a loop doing nothing else reaches roughly 120,000 to 160,000: under 0.2%
        and under 0.7% of a loop's time respectively.

        Checks run: ./scripts/test.sh (pass, including the new
        observability_utilization_smoke), ./scripts/docs.sh (pass, no new warnings),
        ./scripts/bench-runtime.sh.

      9. 6c4bfc3c
        Problem: The guide cannot tell a reader whether a group is busy

        Step 10 of the guide lists the readings that diagnose a group, but every one of
        them describes queue contents. A reader who wants to know whether an event loop
        is saturated has no entry to follow, and the utilization fields the runtime now
        publishes appear only in README.md and the generated API reference.

        Solution: Document loop utilization where the guide diagnoses a group

        A new subsection explains what the runtime measures, why the subtraction is
        always valid, and the two readings that look alike: a group whose tasks all
        wait resembles a group with nothing to do, and a task that never suspends keeps
        its loop out of the poller and reports as fully busy. A decision row places the
        measure next to the queue-depth readings it qualifies. The cost paragraph names
        the measured figures and the script that reproduces them, rather than asserting
        that the accounting is cheap.

        The worked example is compiled and run by tests/guide_utilization_example.adb.
        The first draft of that example did not compile, because Counter is a modular
        subtype and the subtraction needs a use type clause the guide had not shown. A
        test main is the only check that keeps a printed example honest about the
        visibility a reader must supply.

        Checks run: ./scripts/test.sh (pass, including the new
        guide_utilization_example), ./scripts/build-site.sh, and check-site.mjs over
        the built site as CI runs it.

      10. fb881640
        Problem: The utilization copy states a rule that does not hold

        The website/AGENTS.md technical review is required for any changed capability,
        limit, or timing claim, and running it on the new guide section found four
        faults.

        Two are wrong rather than unclear. The guide told a reader that `Counter` needs
        a `use type` clause because the subtype is modular; the clause is needed
        because the operators of a type declared in another package are not directly
        visible, so the stated rule teaches the wrong thing. The guide also said an
        event loop waits in its poller only when no task can run, but the loop polls
        with a zero timeout while work is ready, and the same section counts that
        polling as busy time.

        The remaining two narrow a claim that had become broader than the code.
        "Dispatching, polling with work ready, or running task code" reads as an
        exhaustive account of a loop's busy time and omits timer promotion, file
        submission, and cancellation processing. That wording appeared in the guide,
        README.md, and the Group_Snapshot field documentation, so all three change
        together. `Group_Snapshot` and `Snapshot` appeared only inside the code block
        and were linked nowhere in prose, which the API-link rule does not allow.

        Solution: Correct the two faults and narrow the two broad claims

        The editorial and controlled-language passes contributed three further changes:
        one repeated paragraph opening, "idle fraction" used before the section
        introduces it, and "reading" carrying both a clock read and a snapshot.

        Checks run: ./scripts/docs.sh (pass, no new warnings),
        ./scripts/build-site.sh with check-site.mjs over the built site,
        and observability_utilization_smoke, guide_utilization_example, and
        observability_smoke rebuilt and re-run.

      11. bca8ad7f
        Problem: Previewing the built site needs an ad-hoc server command

        scripts/build-site.sh writes the complete site to build/site, but nothing
        records how to serve it. Reading a guide page as it will be published means
        inventing a static-server invocation each time, and picking a port that does
        not collide with a development server already running.

        Solution: Record a launch configuration that serves the built site

        The entry serves build/site on port 8231. It reads the build output and does
        not produce it, so run scripts/build-site.sh first and again after editing
        anything under website/.

        Checks run: served build/site through the entry and loaded the guide page.

      12. 104d406f
        Problem: macOS L1 detection reports efficiency-core capacity

        The macOS body queries the flat hw.l1dcachesize sysctl. On a heterogeneous
        Apple silicon host that name reports the efficiency-core capacity, not the
        performance-core capacity: one 12P/4E host reports 65536 bytes for the flat
        name against 131072 for hw.perflevel0.l1dcachesize. Flyology_Cachelines.
        L1_Data_Cache_Size therefore reports half the performance-core L1d capacity,
        and L1_Data_Cache_Slots derives its slot count from that halved value.

        The reader also assumed every queried name stores a 64-bit value. It read
        each name into one 64-bit object and accepted a short reply, so a 32-bit
        value was correct only because Darwin is little-endian and the object was
        zero-initialized. The per-level names are 32-bit.

        Solution: Prefer the highest performance level and read the reported width

        macOS 12 and later describe a host whose cores are not identical as ordered
        performance levels, where hw.perflevel0 is the highest-performing level. The
        macOS body now queries hw.perflevel0.l1dcachesize and falls back to the flat
        name only on a host that publishes no performance level, such as macOS 11 and
        earlier or an Intel Mac. Querying hw.nperflevels first would add nothing: the
        per-level name exists exactly when the host publishes performance levels.
        Hardware_Cache_Line_Size is unchanged, because Darwin publishes no per-level
        line size and both Apple silicon core types use the same line.

        The public API keeps its Cache_Query_Result surface. Reporting per-level
        geometry is a separate design question, and it should not ride along in a
        detection correctness fix.

        The sysctl reader moves into a new private Flyology_Cachelines.Macos child,
        mirroring the existing Flyology_Cachelines.Linux split between mechanism and
        policy. It requests each name's stored width before reading the value and
        rejects any other width, so a 32-bit name, a 64-bit name, a string, and an
        absent name are all handled without depending on byte order. Failed and
        malformed queries still degrade to Unavailable rather than raising.

        The GNATdoc comments on L1_Data_Cache_Size and L1_Data_Cache_Slots, the crate
        README, and the website cachelines guide now state that a host whose cores are
        not identical reports one core type, and which one each platform reports. A new
        macOS detection test mirrors the Linux one: it exercises the sysctl reader
        directly and checks that the reported capacity is the highest performance level
        the host publishes.

        Checks run: ./flyology_cachelines/scripts/test.sh (the native test now reports
        131072 bytes of L1 data cache on a 12P/4E host, and the new macOS detection
        test passes) and ./flyology_cachelines/scripts/docs.sh (zero GNATdoc warnings).

      13. d3af8647
        Problem: The Linux detection test requires an optional mechanism

        Flyology_Cachelines.Linux_Testing asserts that both Detect_From_Sysconf and
        Detect_From_Sysfs report a value. Only their composition is guaranteed:
        glibc answers _SC_LEVEL1_DCACHE_SIZE and _SC_LEVEL1_DCACHE_LINESIZE from
        CPUID on x86-64, but reports zero on aarch64, where sysfs is the only
        mechanism. Detect already treats sysconf as optional and falls back to
        sysfs, so the test is stricter than the code it covers.

        The test therefore fails on aarch64 Linux with "sysconf cache detection
        failed". CI runs ubuntu-latest on x86-64, where sysconf answers, so the
        failure is invisible there. It reproduces on aarch64 Linux, which AGENTS.md
        tells contributors to prefer on Apple silicon because it is native and
        faster.

        Solution: Require the composition and check each available result

        Run now requires that at least one mechanism reports a value, and checks
        consistency only for a mechanism that reported one. That is what the
        production detector promises: it composes sysconf and sysfs, and returns
        Unavailable only when neither answers.

        Checks run: the crate suite on aarch64 Linux in a container, where the
        detection test now passes, and on macOS, where it is not built.

      14. 04658ed7
        Problem: Linux cache detection describes only CPU 0

        Flyology_Cachelines.Linux reads one L1 data-cache geometry: sysconf answers
        for the calling CPU, and the sysfs fallback reads cpu0. A host whose cores
        are not identical has more than one geometry, and neither mechanism says
        which core the reported one belongs to, or that others exist.

        macOS already publishes ordered performance levels, so the macOS body can
        prefer the highest-performing one. Linux publishes per-CPU descriptions and
        no single ordering, so the equivalent information has to be derived before
        any public per-core-type query can work on both platforms.

        Solution: Group CPUs into core classes and record what ordered them

        Detect_Core_Classes enumerates the CPUs the host lists as present, reads
        each one's L1 data-cache geometry and capacity, groups CPUs reporting
        identical values into a class, and counts each class.

        Classes are grouped on capacity and geometry together. Grouping on geometry
        alone merges two core types that happen to share an L1 data-cache size,
        which real designs do.

        Ordering uses whichever key separates the classes, and Core_Classes reports
        which one did, so a caller can tell an authoritative order from an inferred
        one:

        - Host_Reported: the kernel's per-CPU capacity values separated them.
        Capacity is the scheduler's own measure of relative CPU performance and
        accounts for microarchitecture and clock. Architectures selecting the
        generic topology code publish it under cpuN/cpu_capacity.
        - Inferred: no capacity separated them, so they are ordered by descending
        L1 data-cache capacity. That holds on current hybrid parts and carries
        no meaning on a host whose classes differ some other way. x86-64 does
        not publish capacity, so its hybrid parts land here.
        - Unordered: fewer than two classes, or nothing separated them.

        Cores and CPUs are counted separately. SMT siblings share one L1 data cache,
        so the cache's sharing list identifies which CPU represents a physical core.
        Counting logical CPUs as cores overstates a 24-core host with two threads
        per core by a factor of two.

        Detection fails closed. A missing or malformed CPU list leaves only CPU 0 to
        enumerate, enumeration is bounded, a CPU whose description cannot be read is
        skipped, and a host reporting more classes than the table holds reports none
        rather than a table that silently omits a class.

        Detect_Core_Classes takes the CPU root as a parameter defaulted to the real
        sysfs path. Grouping, ordering, and the SMT distinction cannot be reached on
        a uniform test host, so the detection test drives them with committed
        fixture trees: two classes separated only by capacity, two classes separated
        only by geometry with the smaller listed first, SMT pairs sharing one cache,
        and a CPU list with a gap.

        Nothing calls Detect_Core_Classes outside the test yet. The public
        per-core-type query, and the elaboration cost of walking every CPU, belong
        to the change that adds that query.

        Checks run: the crate suite on aarch64 Linux in a container and on macOS.
        Detection was also replayed against captured CPU descriptions from a 48-CPU
        x86-64 host with two threads per core, which reports 24 cores against 48
        CPUs and no capacity, and from an 80-CPU aarch64 host, which reports 80
        cores against 80 CPUs and a published capacity.

      15. ba8438da
        Problem: Cache queries cannot name a core class

        Flyology_Cachelines reports one L1 data-cache capacity. A host that combines
        core types has one per type, so a single value silently describes whichever
        type the platform body happened to pick and gives a caller no way to ask
        about the others, or to learn that others exist.

        The two platforms also disagreed. macOS reported the highest performance
        level, while Linux reported whichever cache its own mechanism described:
        sysconf for the calling CPU, sysfs for cpu0. The same call therefore meant
        different things on the two platforms.

        Solution: Make the core class an explicit parameter of every cache query

        Core_Class names one class of cores that report a single cache geometry.
        Core_Class_Count reports how many the host distinguishes, Core_Class_Cores
        and Core_Class_CPUs describe each one, and L1_Data_Cache_Size and
        L1_Data_Cache_Slots take the class they describe. The parameter defaults to
        Fastest_Core_Class, so existing calls keep compiling and now mean the same
        thing on both platforms: the class the host ranks highest.

        Core_Class_Ordering reports what produced that rank, because it is a host
        fact on some platforms and the crate's inference on others. macOS performance
        levels and the Linux per-CPU capacity values are Host_Reported. A host
        publishing no rank is Inferred, ordered by descending L1 data-cache capacity.
        Fewer than two classes is Unordered.

        Cores and CPUs are reported separately. Sibling CPUs under simultaneous
        multithreading share one core's L1 data cache, so a 24-core host with two
        threads per core reports 24 cores and 48 CPUs in one class.

        Hardware_Cache_Line_Size takes no class. macOS publishes no per-class line
        size, and the core types of current heterogeneous parts share one line size,
        so a per-class query would have one answer to give.

        The host is now inspected on first use rather than during elaboration.
        Describing every class means reading one description per CPU on Linux, which
        measures 14 ms for 48 CPUs and 24 ms for 80. A program that links this crate
        and never asks about the host should not pay that at startup. The inspection
        is idempotent, so a race on the first query can duplicate work but cannot
        produce a value neither caller computed; the ready flag is atomic and is set
        after the result is stored.

        Flyology_Cachelines.Platform now answers one Detect call describing the whole
        host, and the root package body owns the single memoization. The two Linux
        bodies share one translation and differ only in what they report when sysfs
        describes nothing: the x86-64 body can still read the calling CPU through
        CPUID. Flyology_Cachelines.Linux drops its own class and ordering types in
        favour of the public ones, so the crate has one Core_Class.

        The website cachelines guide is corrected alongside the API. Adding the Class
        parameter changed the generated GNATdoc anchors for L1_Data_Cache_Size and
        L1_Data_Cache_Slots, so the guide's links to them became dangling fragments;
        both now point at the regenerated anchors. The guide also claimed detection
        happens during package elaboration, which is no longer true. The new entities
        are linked to their generated entries on first mention.

        Checks run: the crate suite on macOS, where a 12P/4E host reports two
        host-ordered classes of 131072 and 65536 bytes across 12 and 4 cores; on
        aarch64 Linux in a container; and on an x86-64 Linux host with 24 cores and
        two threads per core, which exercises the CPUID body and reports 49152 bytes
        across 24 cores and 48 CPUs. GNATdoc builds with no warnings.

      16. 9782c81b
        Problem: The shared L2 cache is not reported

        Flyology_Cachelines reports L1 but not L2, so a caller sizing a working set
        against the level it will actually spill into has nothing to read.

        The flat sysctl this crate would naturally have used is wrong in the same way
        hw.l1dcachesize was, and by a larger factor. On a 12P/4E Apple silicon host
        hw.l2cachesize reports 4194304, the efficiency cluster's cache, against the
        performance cluster's 16777216. Adding L2 before core classes existed would
        have reproduced the original defect at four times the size instead of two.

        Reporting a capacity alone would also mislead. L2 is rarely private: that same
        host shares 16 MiB across six performance cores and 4 MiB across four
        efficiency cores, so neither figure is a per-core budget.

        Solution: Report L2 capacity and how many cores share it, per class

        L2_Cache_Size and L2_Sharing_Cores take the same core class as the L1
        queries. A sharing count of one means the cache is private to a core; a
        larger count means the reported capacity is divided among that many cores.
        The GNATdoc on each function points at the other, because reading either
        alone invites the per-core mistake.

        macOS reads hw.perflevelN.l2cachesize and hw.perflevelN.cpusperl2. Linux
        reads the level 2 entry of each CPU's cache description, counting the CPUs
        its shared_cpu_list names. Both counts arrive as logical CPUs and become core
        counts through the class's own threads-per-core ratio, so a host with two
        threads per core does not report twice the cores sharing a cache.

        Parsing a CPU list needs more than its leading index, so the Linux body gains
        List_Count, which sums the single indexes and inclusive ranges a list names.
        Describing L2 costs no extra file reads: the level 2 entry is found in the
        same pass over the cache indexes that already locates the level 1 data entry.

        The website cachelines guide gains the same pairing, with both names linked
        to their generated entries.

        Checks run: the crate suite on all three supported targets. A 12P/4E macOS
        host reports 16777216 bytes across 6 cores for its performance class and
        4194304 across 4 for its efficiency class, and the macOS test asserts that
        these come from the performance level rather than the flat name. An aarch64
        Linux host reports 16777216 across 6 cores. An x86-64 Linux host with 24
        cores and two threads per core reports 2097152 across 1 core, where sysfs
        gives 2048K shared by CPUs "0,24"; that run also compiles the CPUID body,
        which builds nowhere else. Fixtures cover a per-class shared L2, an L2 shared
        across SMT siblings, and a private L2. GNATdoc builds with no warnings.

    4. 9782c81b updated to 7be049fcindex 6e2db0ef

      1 source commit

      1. 7be049fc
        Problem: A stalled package mirror hangs CI instead of failing it

        The two OpenSSL install steps in the test job carried no bound, so a mirror
        that stops answering leaves apt waiting rather than returning an error. On
        2026-08-19 run 32297071503, job 96211136305 sat on "Install OpenSSL 3 on
        Linux" for 32 minutes and had to be cancelled by hand; it was the only check
        blocking PR #49. Its log shows apt-get update fetching noble-security
        InRelease at 20:13:04 and producing no further output until cancellation. The
        macOS half of the same job passed, so nothing was wrong with the tests.

        Left alone the job would have run to GitHub's six-hour default. Nothing else
        in either workflow was bounded either: the checkout, the Alire install, the
        index configuration, the Java and TLA+ downloads, and the GNATdoc install all
        reach the network under the same default, and no job in this repository
        declared a timeout at all, unlike the sibling repositories.

        Solution: Bound every job and every step that reaches the network

        Each job now declares a timeout-minutes, and so does each step that fetches
        something. The bounds are generous multiples of what healthy runs measure
        over the last 60 successful runs of each workflow, so they can only fire on a
        stall. Jobs: test observes at most 17 minutes on macOS and 11 on Linux and is
        bounded at 60; proof observes 6 minutes and TLA+ 7, both bounded at 30; the
        pages build observes 69 seconds and is bounded at 20, its deploy 10 seconds
        and bounded at 15. Steps: everything network-touching is bounded at 10
        minutes against observed maxima of 1 to 6 seconds, except the Alire install,
        which downloads the toolchain, observes 100 seconds, and is bounded at 15.

        A step timeout alone would only have converted the 32-minute hang into a
        10-minute one, because the stall is inside a single apt-get update that never
        returns. That command is now capped per attempt with timeout(1) and retried
        twice with 15 and 30 second backoff, so one unresponsive mirror costs a
        retry rather than the job. The install that follows is capped as well but not
        retried: a package that cannot be resolved should fail on the first try. The
        worst case is three 120-second attempts plus a 10-second kill grace, 45
        seconds of backoff, and a 190-second install, which is 10m25s and lands
        inside the 12-minute step bound, so the annotation naming the transient
        mirror is what the log ends on rather than a bare cancellation.

        GNU timeout is used directly rather than scripts/run-with-timeout.sh. That
        helper exists for portability to macOS, and this step is Linux-only.

        The TLA+ download gains --connect-timeout 30 and --max-time 120 alongside its
        existing --retry 3, because curl retries a failed transfer but not a stalled
        one, and --max-time resets per attempt. Four bounded attempts stay inside the
        step's 10 minutes.

        Build, test, proof, and model-checking steps keep no step bound. Their
        duration is workload-dependent, a bound sized for them would be a performance
        budget rather than a stall detector, and the job timeout already covers them.
        Nothing about what is installed, or how anything is built or tested, changes.

        Checks run: both workflows parse. The retry script was extracted from the
        committed YAML and driven under bash -e against stub apt-get invocations for
        five outcomes: first-try success runs one update and one install; two
        failures then success runs three updates and installs; three failures exit 1
        with the annotation and never install; an install failure propagates its exit
        status without retrying; and exit 124, which is what timeout(1) reports when
        it kills a stalled command, is treated as retryable. The real commands were
        then run in an ubuntu:24.04 container on coreutils 9.4, the runner's version:
        the bounded update succeeds, interrupting one mid-flight reports 124, a
        retry after that kill still succeeds rather than inheriting a poisoned apt
        state, and the bounded install still yields OpenSSL 3.0.13 through pkg-config.

        The convention is recorded in AGENTS.md so it holds for new steps, and it
        matches the job-level timeouts already used in flyology-http and
        gnat-patches, whose install steps want the same treatment.

        Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

    5. 7be049fc updated to a53da35dindex b5569962

      1 source commit

      1. a53da35d
        Problem: The allocators dependency accepts any version

        The allocator crate is developed alongside the runtime in this repository and
        released on the same development line, but the dependency on it is declared as
        "*". Nothing stops a dependent from resolving an allocator release built for a
        different line, and the index has been carrying a tighter constraint by hand to
        compensate.

        Solution: Constrain allocators to its development line

        Declare the line the allocator crate actually publishes, so the constraint
        travels with the manifest instead of being reapplied wherever it is indexed.

        Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

    Compare source revisions
    Development update

    flyology_http 0.1.1-dev

    4 updates: ddbba90d through dac7fa90

    HTTP client and server library for Flyology tasks

    Manifest fields
    depends-on, origin
    Show all 4 updates
    1. ddbba90d updated to d99490cfindex 510cfcf6

      3 source commits

      1. 1802f1c9
        Problem: Proof and WebSocket qualification depend on manual runs

        SPARK proof regressions and Autobahn conformance failures can go unnoticed because CI does not execute those campaigns. The existing nightly schedule covers other qualifications but not these policy and protocol checks.

        Solution: Gate proofs and schedule Autobahn qualification

        Run the complete QUIC and HTTP proof suite for every CI trigger and add a scheduled matrix for all maintained Autobahn profiles and task lanes, including matched OpenSSL provenance for secure profiles.

      2. 3d0df29f
        Problem: Hosted level-one proofs time out nondeterministically

        The pull request proof job twice exhausts its level-one prover budget on QUIC ACK range obligations, even though the same obligations pass locally. This leaves an otherwise healthy CI run red and makes proof coverage unreliable on hosted runners.

        Solution: Give CI level-two proof effort

        Let both proof scripts accept FLYOLOGY_PROOF_LEVEL while preserving level one as the default for manual runs. Set the CI proof job to level two so hosted provers have enough effort to complete the full QUIC and HTTP campaigns.

      3. d99490cf
        Problem: HTTP benchmark cannot prepare Flyology runtime from worktrees

        The benchmark runner assumes Flyology runtime scripts live in the HTTP project root. Separate Codex worktrees and Alire dependency layouts do not provide that path, so runtime preparation fails before the benchmark can build.

        Solution: Prepare the runtime from the resolved Flyology root

        Resolve Flyology through the shared dependency-root helper and use that root when invoking prepare-rts.sh, preserving explicit, adjacent monorepo, and Alire-provided dependency layouts.

    2. d99490cf updated to d99490cfindex 28a2302d
    3. d99490cf updated to 439a9fb6index 6e2db0ef

      30 source commits

      1. 24c1ea29
        Problem: Running routers cannot be reconfigured atomically

        Servers must currently mutate route setup state directly and cannot safely publish coordinated handler, policy, and middleware changes while requests are in flight. Callers also lack stable identities for addressing registered routes and middleware.

        Solution: Publish immutable router generations through stable identities

        Add opaque route and middleware IDs, transactional update operations, stale-writer detection, and single-load atomic generation publication. Exercise replacement and concurrent dispatch behavior, document the runtime and memory tradeoffs, and add the workflow to the server guide.

      2. 5e5aae59
        Problem: Router publication adds a generation indirection

        Every dispatch loads the published generation and then follows a second pointer to reach its immutable configuration. Each successful update also allocates a separate generation holder solely for retention bookkeeping.

        Solution: Publish configuration allocations directly

        Link retained configurations through their own private history field and atomically publish the configuration address. This removes the holder allocation and one dependent request-path load without changing stale-update or lifetime behavior.

      3. 1df8c3a6
        Problem: Retained router generations are linked by raw address

        The retention chain, the publication gate, and the update base all carry
        System.Address, so recovering a configuration needs an unchecked conversion
        from an address-conversion pointer into a pool-specific access type. Router
        initialization also allocates its first configuration in the declarative
        part, where the handler written to release a failed allocation cannot see
        it: an exception raised there propagates without reaching the handler.

        Solution: Link retained configurations through a typed access

        Complete the configuration type from an incomplete declaration and make its
        access type general, so Previous, First_Configuration, the update base, and
        the publication gate all hold access values and the unchecked conversion
        disappears. The address round trip now stays on the published atomic word
        alone. Allocate the first configuration in the statement part so its handler
        covers the allocation it was written for.

      4. 38b98060
        Problem: Direct registration can tear a generation being served

        Add, Add_Middleware, Add_Route_Middleware, Mount, and the two direct setters
        write the currently published configuration in place, and they admit the new
        element before they write it: the count is incremented first. A request that
        races such a registration reads the raised count and then a route with a null
        handler or a middleware entry with a null component, so the pipeline raises
        Constraint_Error. Only the two setters carried a setup-only note, and the
        identity-returning registration overloads carried none.

        Solution: Seal the router at its first dispatch

        Publish a seal word from the first dispatch and refuse every direct
        registration and setter afterwards with Route_Error naming the update path.
        The dispatch cost is one acquire load of a clean shared line, since the store
        happens only while the word is still clear. Fill each route and middleware
        slot before the count admits it so the ordering is sound on its own, and
        state the sealing rule on the router type and the affected operations.

      5. 1fd5ed9b
        Problem: Mounting makes a middleware registration unaddressable

        Mount assigns a fresh identity to every middleware entry it copies into the
        mounted routes, so the identity the application holds for a subrouter's
        component matches nothing in the destination. Remove_Middleware and
        Replace_Middleware then raise while the mounted copies keep running the old
        component, even though both already walk every route chain accumulating
        matches, which only makes sense when one identity can appear in several
        chains. Begin_Update also accepted a mounted generation, and two candidate
        setters skipped the mounted guard the other mutators apply.

        Solution: Carry the source registration identity through a mount

        Copy mounted middleware entries verbatim so one identity names every chain
        that carries the registration. Refuse Begin_Update on a mounted generation,
        which covers every candidate mutator in one place, and add the guard to the
        admission and challenge setters that lacked it. State the mounting rule on
        the identity type, on Remove_Middleware, and in the server guide.

      6. 8244e2fb
        Problem: A stale candidate cannot be rebuilt in the same update

        Commit raises Stale_Update while the candidate is still attached, so
        Begin_Update on that object then raises Program_Error. The documented retry
        loop only works because it declares the update inside the loop; hoisting it,
        which is the obvious way to avoid re-entering the declaration, deadlocks the
        caller into an unusable object. There is also no way to give up on a
        candidate that failed validation.

        The concurrency audit could not fail cleanly either. Its workers park on a
        barrier that a failure before Start never opens, and the join waits for all
        four to finish with no bound, so a setup error hangs the audit until the
        harness timeout instead of reporting. Its assertion also could not tell a
        run that spanned a publication from one that never observed a change.

        Solution: Release a stale candidate and bound the audit

        Release the candidate when Commit rejects it as stale, since its base is gone
        and it can never be published, and leave a validation failure active so the
        caller can correct and commit it. Add Abandon for an explicit discard.

        Rebuild the audit around a cancellable barrier, bounded joins, and a fixed
        publication count chosen odd so the closing request of every worker has one
        correct answer. Workers now record a pre-publication and a post-publication
        observation, so the test proves it spanned a generation change. Cover the
        duplicate-name and ambiguity rejections that candidate Add defers to Commit,
        and the Set_Match, Rename, Set_Middleware_Stage, and admission operations
        that had no coverage at all.

      7. 5e9b0b41
        Problem: Introspection loops can straddle a router commit

        Every introspection operation takes its own acquire load, so a caller that
        reads Route_Count and then describes each index reads two generations. A
        commit that removes a route between the two calls makes the last index
        invalid and Describe_Route raises Constraint_Error. The same split affects
        Route_Middleware_Count with Describe_Route_Middleware. A diagnostics endpoint
        enumerating routes therefore fails intermittently on exactly the deployments
        runtime reconfiguration is for, and nothing lets a caller pin a generation.

        Solution: Add a snapshot that pins one generation

        Add a Snapshot that captures the published generation, with the whole
        introspection surface available on it. Route the Router forms and the
        Snapshot forms through shared configuration-level operations so both answer
        identically. Retained generations already outlive any snapshot, so the
        snapshot only holds a reference; its finalization is the hook a later
        reclamation scheme needs.

      8. b345dc6f
        Problem: Retained router generations are neither visible nor releasable

        Commit links every superseded configuration into the router's retention
        chain, and only router finalization frees it. Retention is what keeps an
        in-flight dispatch from reading freed storage, but nothing bounds it and
        nothing reports it: a control plane that commits periodically grows the
        chain for the whole process lifetime with no way to observe the growth and
        no way to release it short of destroying the router.

        Solution: Report retained generations and release them on demand

        Add Retained_Generations so the growth is measurable, and Reclaim to release
        every superseded generation while keeping the published one. Reclaim states
        its precondition plainly: the caller must know that no dispatch is running
        and no snapshot of a superseded generation is live, and that is not checked.
        This keeps the request path free of reader accounting while giving a drained
        server a way to return the memory.

      9. e0a9e1b8
        Problem: Ambiguity checks re-split patterns they already compiled

        Registration compiles each pattern into a Segment_List so dispatch does not
        split it per request, but the ambiguity checks throw that away. Patterns
        Overlap and Specificity both take a String and split it again, so Check_Add
        re-splits every stored pattern on every registration and Commit re-splits
        both sides of every route pair. Add also computed the same split twice, once
        for storage and once for the score. The name-keyed Add_Route_Middleware
        scanned for the name, took an identity, then re-read the router and scanned
        again for that identity, which can report an identity failure for a name
        that does resolve. Name comparisons allocated a String per route inspected.

        Solution: Compare the segments and score each route already carries

        Take a Segment_List in Patterns_Overlap and Specificity, so both the
        registration check and the commit check read the stored segments and the
        stored score. Order the cheap score comparison before the segment walk.
        Compile each pattern once per Add. Resolve the name-keyed middleware
        overload in one pass over one generation. Compare names against the stored
        Unbounded_String instead of converting each one.

        Cover the result with an oracle: for each of eight pattern pairs, assert the
        registration decision and the commit decision are both the expected verdict.

      10. bdcfbc8c
        Problem: The server guide predates the update lifecycle it describes

        The guide still tells applications to bound their update rate when retained
        memory matters, which describes a rate tradeoff rather than growth the
        router now reports and can release. It states that direct registration must
        not run concurrently with dispatch without saying the router enforces that.
        It describes per-call introspection as a snapshot, which is what the new
        Snapshot type actually provides, and it tells a caller to rebuild a stale
        candidate without saying the candidate is already released.

        Solution: Describe sealing, snapshots, and generation retention

        Replace the retention paragraph with Retained_Generations and Reclaim, and
        state Reclaim's unchecked precondition beside the call. Say that the first
        dispatch seals the router and what a later direct registration raises. Add a
        short section for traversing one generation with Take_Snapshot, and record
        that Stale_Update releases its candidate while a validation failure keeps
        one for correction. Every new API mention links its generated GNATdoc entry,
        and all 286 generated-API links on the hand-written pages resolve.

      11. 799995fd
        Problem: A generation can be copied into a dispatch parameter

        Router_Configuration is a large non-limited discriminated record, so RM 6.2
        leaves by-copy or by-reference to the implementation for an in parameter.
        Dispatch_Configuration takes a generation that way, and so does every
        introspection and validation operation that reads one. GNAT passes them by
        reference and the request-path measurements show no copy, but nothing in the
        language requires it. An implementation that chose by-copy would duplicate a
        whole generation, with every route pattern, segment list, and middleware
        name, on each request.

        Solution: Take every generation parameter explicitly aliased

        An explicitly aliased parameter is passed by reference by definition, so
        mark all fourteen Router_Configuration parameters aliased. Every actual is
        already an aliased view reached through a Configuration_Access, so no call
        site changes. The guarantee is now a property of the declaration rather than
        of one compiler's choice.

      12. 977add4a
        Problem: No benchmark isolates dispatch against router reloads

        The published-generation word a dispatch reads and the word a commit writes
        live in the same router object, so a reload can invalidate the line the
        dispatchers are reading. Nothing measures that. The existing benchmark
        servers run over sockets and an external load generator, where connection
        and syscall cost hides an effect this small, and none of them reload the
        router while traffic runs.

        Solution: Add an in-process router reload benchmark

        Drive routed dispatch from worker tasks over an allocation-free in-memory
        transport, with one loader task republishing the configuration at a chosen
        rate, and sweep that rate against otherwise identical traffic. Each worker
        counts on its own stack and reports once at the end, so the harness adds no
        contention of its own to the thing being measured.

        The runner repeats each rate as independent process runs and reports best,
        median, worst, and spread, because code layout changes per link and process
        placement dominates repetition inside one run. Reporting the spread is the
        point: an effect smaller than it cannot be claimed from this harness.

      13. 926fed4b
        Problem: The router's dispatch-read words share a region with writer state

        Every dispatch reads the published-generation word and the seal word. Both
        sit in the same record as First_Configuration and the publication gate,
        which only a commit touches, and nothing in the declaration separates the
        two groups. Whatever layout the compiler happens to produce today is a
        consequence of field order and padding, not a property anyone stated.

        Solution: Place the two dispatch-read words in one interference region

        Group them with Flyology_Cachelines.Padded_Groups, so a dispatch fetches one
        region rather than two and a commit dirties the readers' region rather than
        whatever else landed beside it. The two words have the compatible ownership
        that a group requires: each is read by every dispatch and written only by a
        commit.

        This is not a measured improvement and must not be read as one. A commit
        dirties the readers' region once, not once per dispatch, so the cost follows
        the reload rate rather than the traffic: between 10 and 100 reloads per
        second it is 0.0004% to 0.004% of throughput, four orders of magnitude below
        what the reload benchmark can separate from run-to-run spread. The change is
        made because the layout is then correct by declaration instead of by
        accident. The benchmark now records what it can and cannot resolve, so the
        question is not reopened on the assumption that a measurement is available.

      14. 8cae2c89
        Problem: A stalled package mirror burns a runner instead of failing

        The HTTP/2 qualification job installs its independent peer with a bare
        sudo apt-get update, and no step in either workflow bounds its own runtime.
        When the mirror stops answering, apt-get does not fail; it waits. The step
        waits with it, and the only thing that eventually ends the run is the job
        timeout, or a person noticing.

        On 2026-08-19 that happened three times. Run 32226557711 on main sat on the
        update for the whole 150-minute job budget before the job timeout ended it,
        with nobody watching. Runs 32278682887 and 32294697524 sat there 83 and 64
        minutes before someone cancelled them by hand. The same job finishes in 8 to
        14 minutes when the mirror answers, and the install itself takes 11 seconds
        at the median, so each of those runs spent between four and eleven times the
        job's whole healthy duration waiting on one command. A run that hangs also
        reads as a run that is working: there is no failure to retry, and the
        concurrency group keeps the branch occupied until someone intervenes.

        Solution: Bound every network step, and retry the update that stalls

        Give each step that reaches the network a timeout-minutes bound, sized
        against the slowest healthy observation over the preceding 60 runs rather
        than against a guess, so a step that trips one has stalled rather than run
        slowly. Checking out sources and configuring the index finish in seconds and
        are given 5 minutes; the peer install runs 11 seconds at the median and 5
        minutes at its slowest and is given 15. Installing Alire is given 15 on
        different grounds: every observation of it is a cache hit, so the
        observations bound the cached path and say nothing about a cold toolchain
        download.

        Wrap apt-get update in three attempts, each bounded on its own by timeout,
        because the step bound alone would convert a stall into a failure but not
        into a recovery. A wedged mirror connection now becomes a retry against a
        fresh one, so a single transient failure does not fail the job, and the step
        bound stays a backstop rather than the mechanism that catches the common
        case. Only the update is retried: it is the command that stalled, and it is
        the one here that is safe to interrupt and repeat, since a killed run leaves
        partial package lists that the next run refetches. Retrying apt-get install
        would risk resuming from a half-configured dpkg state to no purpose.

        The same failure mode existed in two other places and is closed the same
        way. The Pages workflow had no job-level timeout at all, so a stall there ran
        to the six-hour GitHub default; both its jobs now carry one, and its fetch
        and install steps carry step bounds. The h3spec download in the HTTP/3
        conformance script used a bare curl -fL, which hangs on a stalled connection
        exactly as apt-get did; it now retries with a per-attempt time limit, which
        the existing checksum makes safe, because a truncated or resumed body never
        survives it.

        Nothing about what is installed or how anything is built or tested changes.
        On a healthy run every bound is untouched and every command runs as before;
        the bounds only decide how a stalled run ends.

        Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

      15. 27a8ee59
        Problem: the component getters and Resolve are unmeasured

        flyology_iri_benchmark times can_parse and parse_href over the pinned URL corpus. Neither reaches a component getter: can_parse constructs nothing, and parse_href consumes only the stored serialization length. The paths that read components back out of an already parsed reference, and Resolve above them, have no benchmark at all, so a change to them can be argued only from reading the code.

        Solution: Add a flyology_bench harness for those paths

        flyology_iri_resolve_benchmark reads all eight components at three reference lengths and resolves the RFC 3986 section 5.4 references against a short and a long base. It carries its own inputs, so unlike benchmark.sh it needs neither the Ada URL checkout nor the pinned corpus. Batches fold a value derived from each result into an accumulator handed to a barrier after the ending timestamp, and each iteration advances to a different input.

        Two builds of one library cannot share a process, so before/after runs join through Flyology_Bench.Baselines, whose fingerprint refuses a comparison across operating system, architecture, compiler, or build mode while deliberately excluding the library revision. scripts/resolve-benchmark.sh selects the release mode the published medians measure and passes it to the binary for that fingerprint. Diagnose and Parse do coexist, so the validation pair is a real paired Compare.

        Requested axes are Process_Resource_Metrics, the portable Darwin/Linux set; the metrics CSV reports each axis's collection status rather than leaving it assumed.

      16. d45630c0
        Problem: Slice copies the whole reference for one component

        Every public component getter reaches the stored serialization through the private Slice helper, which materialized the entire reference with To_String and then returned one range of it. The release objects show that call sited unconditionally and ahead of the zero-span test, so an absent component paid a whole-reference copy and a present one paid two allocations and two copies. Reading a four-character scheme out of a 233-byte IRI copied 233 bytes and then four. Resolve sits directly on top of that and reads Path four times and the base path twice. Remove_Dot_Segments, which runs on essentially every resolution, renormalized its input to one-based indexing through an Unbounded round trip.

        Solution: Copy only the component, and read each path once

        Slice now calls Ada.Strings.Unbounded.Slice, keeping the zero guard ahead of it because an absent component has First = 0 and that subprogram takes a Positive Low. The getters compile to a tail call to that subprogram on the present path and to an eight-byte bounds allocation on the absent one. The returned bounds do not change: GNAT's Slice returns the underlying Low .. High range, which is what the discarded whole-text copy was sliced by. Remove_Dot_Segments renormalizes with a constrained subtype instead of the heap. Resolve hoists the relative path and the base path into locals.

        Release-mode medians on an Apple M3 Max, interleaved before/after/before/after against an unrelated build holding the load average near 25, with the repeated pre-change round as a drift control: reading all eight components falls 41.9% at 44 bytes, 33.5% at 235, and 63.8% at 2,009; resolution falls 22.2% against an 18-byte base and 15.5% against a 233-byte one. The drift control landed within 3% of its own first round. Process_RSS_Change and both page-fault axes read zero on both sides, as expected for churn the allocator reuses within a batch; wall time and thread CPU time are the axes that respond.

        Component tests now name the absent components, since the zero guard is what keeps an absent span away from a Positive parameter.

      17. 4df3c149
        Problem: Resolve builds a Reference its caller may not want

        Resolve ends by parsing its assembled result into a second Reference, a heap serialization plus eight component spans, purely to establish that the bytes are well formed. A caller that stores resolved references as opaque bytes needs exactly that guarantee and none of the spans, and has no way to ask for it.

        Solution: Add a serialization-returning Resolve

        Diagnose establishes the same guarantee without constructing anything, and for URI and IRI it is the same computation Parse performs: both reduce to Analyze's error, and a successful non-web parse stores its input verbatim. Web mode normalizes, so there the normalized serialization is the result and the new form still parses to obtain it. The value equals Image of the Reference the other form returns, which the section 5.4 suite now asserts on every case it already covered.

        The two forms share a private Assemble rather than one calling the other. Composing them the obvious way, with the Reference form parsing the serialization form's result, would make it validate twice and cost it roughly 210 ns it does not pay today.

        Paired Compare in one process, release mode, against a 233-byte base: 821.3 ns/op returning a Reference against 743.4 ns/op returning a String, 9.45% less, 95% CI [1.102, 1.107], winning 100 of 100 sample pairs at an order effect of -0.46%. Isolating the validation step, Diagnose measures 211.2 ns/op against Parse's 270.1. The end-to-end saving exceeds that difference because the serialization form also skips constructing and finalizing the result Reference, not only the parse that fills it. The Reference form's median is unchanged, which is what confirms it kept its single validation.

      18. cfb25efc
        Problem: resolution assembles through a growing Unbounded_String

        Resolve merges and reduces its result by appending to an Unbounded_String, which reallocates on nearly every append, and by calling Remove_Dot_Segments, which builds a second one and returns To_String of it. Segment removal is worse than that suggests: collapsing one "/../" runs a whole To_String followed by a Set_Unbounded_String. None of this is visible in the API, and all of it is on the path of every resolution.

        Solution: Assemble into a String sized from the parsed references

        Merging and dot-segment removal never produce more than the base, the relative reference, and the separators between them, so the serialized lengths of the two parsed references bound the result. Both are real lengths rather than Max_Length, which may be Positive'Last, and both come from parsed references rather than input bytes, because web normalization can expand a relative past what it was written with. A bound above what belongs on the stack takes one exact allocation instead, which keeps a single copy of the merge rather than a rarely exercised second implementation.

        Release-mode paired medians against a 233-byte base: the Reference form falls from 823.2 to 550.4 ns and the serialization form from 743.4 to 466.5, so the change reaches the API every existing caller already uses. Resolution against an 18-byte base falls from 475.8 to 331.0. The public specification is untouched.

        A procedure form writing into a caller-supplied buffer was prototyped against this and measured 4.7% below the serialization form, winning 69 of 100 pairs. That difference is the returned copy alone, which is all the wider API buys once the assembly no longer allocates, so it is not adopted.

      19. 616fdfd5
        Problem: large resolutions overflow the stack and leak on failure

        Assembling into a buffer put four objects proportional to the reference length on the primary stack: the one-based copy of the dot-segment input, the merged path, the prefix taken out of the base path, and the result staged on the way out of the heap branch. The heap branch existed precisely so that a caller raising Max_Length would not put a large buffer on the stack, and then reached the stack anyway through the other three. Resolving a four megabyte base raised Storage_Error where the previous implementation returned a result. The heap branch also freed its buffer only on its two normal exits, so any exception through it leaked the allocation, and neither the bound nor the append guard was safe against wraparound in a body whose release profile suppresses overflow checks.

        Solution: Keep every size-proportional object off the primary stack

        Dot-segment reduction indexes its input through an offset rather than copying it one-based, so the copy is gone rather than moved. The prefix is named by bounds into the base path and written straight into the merged buffer. The merged path takes the same stack-or-heap fork as the assembly buffer, because section 5.2.4 reduces the joined path as one string and the pieces cannot be reduced separately. An extended return builds the result where the caller wants it. Both heap blocks free their allocation from an others handler as well as their normal exits.

        The append guard subtracts rather than adds, so it cannot wrap, and the bound is computed in Long_Long_Integer and rejected unless it fits Natural with room to spare, which also keeps every later index lookahead inside range.

        Resolving against bases of one hundred kilobytes, four megabytes and forty megabytes now all succeed, matching the previous implementation. A differential harness comparing both public forms against a verbatim reimplementation of the previous assembly reports no divergence over 429,208 cases, of which 105,202 raise on both sides.

      20. 18ecffdb
        Problem: the serialization Resolve overloads on result type silently

        Resolve returning String and Resolve returning Reference differ only in what they return. Most calls select between them from context, but a call whose context supplies no type does not: comparing two resolutions with "=", or taking an attribute of one, becomes ambiguous. Both were legal while only the Reference form existed, so an existing caller of the published crate meets a compiler error whose cause is not apparent from the code in front of it.

        Solution: Say so where the operation is documented

        Record the overload, name the two shapes that stop compiling, and give the disambiguation. A qualified expression settles either in place, and naming the result in a constant always works. Keeping the shared name is deliberate: the failure is a compile error rather than a silent change of meaning, and the fix is local to the call.

      21. 2f3df5f8
        Problem: the published resolution figures predate the stack fix

        BENCHMARKS.md carries medians taken before the assembly stopped staging size-proportional locals on the stack, and its comparison between the two assemblies stitches together runs from separate sittings on a host under varying load.

        Solution: Re-measure both assemblies in one interleaved sitting

        Swap the two assemblies in place across four rounds, first arm repeated as a drift control, and report the resolution rows from that. The control landed within 0.4% of itself. Removing the one-based copy from dot-segment reduction moved the figures slightly in its favour, so the buffer assembly now reads 34% below the Unbounded one for both public forms rather than 33%.

      22. 4b7b1d6c
        Problem: Admitting a reference costs a serialization copy

        Can_Parse and Diagnose report whether input parses but not how it
        classifies, so a caller that admits only absolute references -- an RDF
        crate deciding whether bytes are an absolute IRI, say -- has to reach for
        Try_Parse. Try_Parse builds a Reference, and building one stores a copy
        of a serialization that is byte for byte the input the caller already
        holds. The caller reads Kind and drops it.

        Solution: Report the classification without building the reference

        Add Inspect, which runs the analysis Try_Parse runs and reports the
        structural kind alongside the parse error. Analyze works on spans over
        the caller's String, so nothing is stored and nothing is allocated. The
        differential harness now holds Inspect to Try_Parse on both the error and
        the kind across the whole seeded corpus.

        Admitting "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" as an
        absolute IRI:

        allocs bytes ns
        via Try_Parse 1 80 145
        via Inspect 0 0 103
        -100% -100% -29%

        Measured with FLYOLOGY_IRI_BUILD_MODE=release. Both forms were run
        alternately, eight rounds each, and the minimum taken, because the host
        carries unrelated build load. Allocation counts are exact.

      23. bc3e3217
        Problem: Preprocessing copies every URL that needs no preprocessing

        Preprocess removes tab, newline and carriage return by appending the
        surviving bytes to an Unbounded_String one at a time. Almost no URL holds
        any of them, so the ordinary case takes an accumulator, grows it, and
        returns a verbatim copy of its own input.

        Solution: Return the trimmed slice when there is nothing to remove

        Scan first and build only once a byte has to be dropped, which also keeps
        the controlled accumulator out of the common path entirely. The slice is
        slid to one because Input_Offset and the parser below read the result at
        one-based offsets.

        Absolute web URLs that take the WHATWG pipeline rather than the fast
        path:

        allocs bytes ns
        web_slow, before 25 1008 2072
        web_slow, after 23 912 1964
        -8% -10% -5%

        web_idna, before 16 752 1661
        web_idna, after 14 656 1547
        -13% -13% -7%

        Measured with FLYOLOGY_IRI_BUILD_MODE=release. Revisions were built into
        separate worktrees and run alternately, eight rounds each, minimum taken,
        because the host carries unrelated build load. Allocation counts are
        exact.

        WPT URL conformance stays at 919/919 with no mismatches.

      24. bf79ef49
        Problem: Percent-encoding and decoding build their results on the heap

        Encode, Encode_Opaque_Path and Percent_Decode each accumulate into an
        Unbounded_String one character at a time and then copy the whole thing
        out with To_String. That is a heap block, the reallocations that growing
        it byte by byte implies, and one full copy, for a result whose length is
        a pure function of the input. Two of the callers encode a single
        character at a time inside a loop, so each iteration paid all of it.

        Solution: Count the result, then write it into the returned object

        Each function now measures its output in a first pass and fills an
        extended return object in a second. Since the count is exact, the
        returned String is the only storage involved -- no accumulator and no
        working buffer, so nothing is allocated and nothing is copied.

        Sizing a buffer up front was the alternative, but the bound that is known
        a priori is three bytes per input byte, and with Max_Length at one
        mebibyte that reserves three mebibytes on the stack in a crate that does
        not build with -fstack-check. Counting first costs a second pass over the
        input and reserves exactly what the result needs.

        Absolute web URLs that take the WHATWG pipeline rather than the fast
        path:

        allocs bytes ns
        web_slow, before 23 912 1964
        web_slow, after 17 720 1670
        -26% -21% -15%

        web_idna, before 14 656 1547
        web_idna, after 12 592 1449
        -14% -10% -6%

        Measured with FLYOLOGY_IRI_BUILD_MODE=release. Revisions were built into
        separate worktrees and run alternately, eight rounds each, minimum taken,
        because the host carries unrelated build load. Allocation counts are
        exact and do not depend on any of that.

        The corpus benchmark does not move: over the pinned 100,025 URLs,
        can_parse holds at 22 ns minimum and parse_href at 105 against 103, with
        acceptance identical at 99999. That corpus is dominated by URLs taking
        the allocation-free fast path, which never reach either function.

        WPT URL conformance stays at 919/919 with no mismatches, which is the
        corpus that exercises these two functions hardest.

      25. 82106435
        Problem: The API reference links to pages the generator never writes

        Since "The router's dispatch-read words share a region with writer state",
        routing.ads groups its two dispatch-read words with
        Flyology_Cachelines.Padded_Groups. That spec is one of the files the
        documentation build documents, and GNATdoc walks every project in the
        closure that Documentation.Excluded_Project_Files does not name, so the
        private with dragged the cachelines crate in with it. Its two tagged
        types, Fitted_Groups.Grouped_Array and Padded_Groups.Grouped_Array, then
        appeared in the index's tagged-type section, each linked to a page of its
        own -- and GNATdoc writes a page per tagged type only under
        --html-oop-style, which this build does not pass. This crate's own tagged
        types are linked as unit page plus fragment and resolve; those two never
        could.

        The site check reports both as missing targets, so the Pages workflow has
        failed on every push to main since that commit landed and the published
        site is frozen at the last green deploy. CI is unaffected: the two
        workflows fail independently, and only one of them was ever red.

        Solution: Document this crate and nothing else

        Name every dependency in Excluded_Project_Files, beside the Flyology
        runtime that was already there. Excluding cachelines alone would clear the
        two broken links, but the closure walk is why they were reachable at all,
        and the same walk had already put twenty-four pages of QUIC and allocator
        internals into a reference whose own footer reads "Public HTTP API only".
        The index now lists this crate's sixty-two entries, the search index
        carries 2441 names with none from a dependency, and no page outside
        Flyology.HTTP is written.

        Removing those pages breaks no link. Their only inbound references were
        the index entries that go away with them: scanning every website page and
        every generated page for their file names finds nothing else pointing at
        them.

        Each exclusion names its project through the prefix Alire exports for that
        crate rather than a path under FLYOLOGY_ROOT. The Flyology crate vendors
        copies of the cachelines and allocator sources, so the two resolve to
        different build directories, and GNATdoc rejects an excluded file that is
        not the project it loaded -- "unable to resolve project file path", a hard
        error rather than a silent no-op, so naming the vendored copy fails the
        run outright. A bare project name fails the same way.

        Verified with docs/api deleted first, since the workflow builds from a
        fresh checkout and a stale page left behind by an earlier run would hide a
        link the workflow cannot resolve. scripts/build-site.sh, which is what the
        workflow runs, reports "Site check passed: 70 HTML files and 136 total
        files".

        Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

      26. 83db8c4d
        Problem: A discarded QUIC Initial ends the HTTP/3 integration exchange

        The dual-stack overload of Routing.Serve divides HTTP_3_Capacity between the
        address families, so HTTP_3_Capacity => 8 gave each listener four connection
        slots rather than eight. Both client profiles in this test address
        "localhost", which resolves to every loopback family on some hosts, and the
        client's connection race completes a full QUIC handshake on each family
        before it discards the losing lane. Each family therefore admits up to five
        concurrent connections here: two live client profiles, two losing race lanes
        awaiting release, and the raw Initial. Instrumented runs reach four of four
        slots routinely.

        A listener whose registry is full discards an Initial without answering it,
        and no handshake-space probe timeout retransmits one. The raw handshake loop
        compounded that: its receive raised Flyology.IO.Timeout_Error straight out of
        the loop, so the eight attempts were never a retry budget and the first quiet
        interval ended the run. The response loop had the same shape. Sizing a run of
        twenty at each capacity reproduced the failure in nineteen runs at two slots
        per family, seven at three, and one at four, tracking the discarded Initials
        one for one.

        Solution: Retransmit the handshake flight and size the listener for the load

        Retain the last flight sent to the server and resend it when a receive
        expires, spending the attempt budget on eight two-second probes rather than
        one ten-second wait. The response loop keeps its budget for waiting, because
        the server does drive application-space probe timeouts and retransmits on its
        own; sixteen one-second probes stay inside the server's connection age.
        Neither loop now ends an exchange on a single discarded datagram.

        Raise HTTP_3_Capacity to sixteen and record the actual per-family model in
        the comment, so the test stops running its listeners at full occupancy by
        accident. With the retransmission in place the capacity is no longer load
        bearing: at two slots per family, where the previous loop failed nineteen
        runs of twenty, the raw handshake now completes in all twenty.

        This is a test change. The absent handshake-space probe timeout is a real gap
        in the QUIC layer and is not addressed here.

      27. d7d87344
        Problem: A QUIC endpoint cannot close before its handshake completes

        CONNECTION_CLOSE is only reachable through the application space. An endpoint
        that abandons a connection while it still holds Initial or Handshake keys has
        no way to say so, and Build_Application_Close_Datagram's precondition rules it
        out.

        The receiving side is missing too. Initial_Space and Handshake_Space parse a
        peer Transport_Close frame, count it, and discard it. A peer that did somehow
        send one would be ignored, so adding a builder alone would change nothing
        observable.

        Solution: Report a peer close from both spaces and expose a close builder

        Initial_Space and Handshake_Space now carry Peer_Closed and Close_Error in
        their Process_Result and stop parsing at the frame, since RFC 9000 10.2.2 puts
        the receiver into the draining state and the rest of the packet cannot change
        that. Connection_Driver acts on it exactly as it already does for the
        application space: Peer_Closed state, Connection_Closed status.

        Build_Handshake_Close_Datagram builds the outbound half in the highest space
        the connection holds, Handshake once that space exists and Initial otherwise,
        so a peer that reached either level can read it. It carries the transport
        APPLICATION_ERROR code that RFC 9000 10.2.3 reserves for an application close
        that its encryption level cannot express, and leaves the connection Failed
        because an endpoint that has begun closing must send nothing else.

        Initial_Space.Build_Transport_Close_Packet passed a zero minimum packet length
        for both roles, so a client-sent Initial close fell under 1,200 bytes and RFC
        9000 14.1 requires a server to discard it. It now derives the minimum from the
        role, as Build_Crypto_Packet already did. That also corrects the existing
        client Fail_Initial_With_Close path, whose closes were unreadable for the same
        reason.

      28. c041b36d
        Problem: A lane that loses the address-family race abandons its handshake

        For HTTP/3 both lanes of the address-family race run Start_Connection, which
        completes a full QUIC handshake before Race.Choose picks a winner. The loser
        raises Connection_Race_Lost, Close_Candidate runs, and Dispose_Connection sends
        an application CONNECTION_CLOSE only when the transport reached the connected
        state. A lane cancelled mid-handshake never did, so the client closes its UDP
        socket and says nothing.

        The server is left waiting for a handshake that will never arrive. On a bounded
        listener that costs a connection slot for the whole handshake timeout, and a
        peer that repeatedly starts and abandons handshakes can hold every slot.

        Solution: Send a handshake-space close from the abandoned lane

        Dispose_Connection now picks the close by transport state rather than skipping
        it: an application close when connected, and Build_Handshake_Close_Datagram
        when the connection is still in Client_Initial or Client_Handshake. Both go out
        on the connection's own UDP socket before it closes, and both remain best
        effort, since a disposal path cannot report a send failure to anyone.

      29. fe4a9d4d
        Problem: A silent peer holds a listener slot for the whole handshake timeout

        Serve_Connection waits for QUIC.Is_Connected against one deadline, the absolute
        handshake timeout measured from the connection epoch. A peer that sends an
        Initial and then stops answering is indistinguishable from one that is merely
        slow, so its worker waits out the full budget and its Connection_Registry slot
        stays taken. A cooperative peer now sends a close, but a crashed, partitioned,
        or hostile one still does not.

        Solution: Deadline an unconnected peer on no progress as well as elapsed time

        Connection_State records the arrival of each inbound datagram, and the
        pre-handshake wait takes the earlier of the absolute handshake deadline and
        that arrival plus Handshake_Idle_Timeout. The absolute budget still bounds a
        peer that keeps sending; the no-progress budget reclaims the slot from one that
        stops.

        Default_Handshake_Idle_Timeout is three seconds. Handshake retransmission on a
        lossy path arrives well inside that window and counts as progress, so only a
        silent peer reaches it. Serve_Listener and both Serve overloads take an
        override. Routing.Serve is left alone: it gets the shorter reclamation from the
        default without adding a parameter to eight overloads.

      30. 439a9fb6
        Problem: Nothing checks that an abandoned handshake frees its listener slot

        Both reclamation paths, the peer's transport CONNECTION_CLOSE and the server's
        no-progress deadline, are only observable as the absence of a stall. No test
        saturates a bounded listener with half-open handshakes, so either could regress
        into the ten-second wait it replaced without a failure anywhere.

        Solution: Saturate a listener of capacity N and require a fresh Initial

        http3_handshake_abandon runs two phases against a capacity-three listener whose
        handshake timeout is twenty seconds, far beyond every deadline it asserts, so a
        slot reclaimed inside one of them cannot be explained by that timeout. Each
        phase fills every slot with a handshake that will not complete, asserts that a
        further probe is refused, releases the lanes, and then requires a fresh Initial
        to be admitted.

        The first phase abandons with closes and leaves the no-progress deadline out of
        range; the second goes silent and relies on the deadline alone. Odd lanes
        consume the ServerHello first so they abandon from the Handshake space, while
        even lanes abandon from the Initial space, covering both protection levels. The
        probe repeats its Initial while no worker answers, the way a real client's probe
        timeout would, so a slot released partway through the budget is still taken up.

        Each phase was confirmed to fail on its own: removing the driver's peer-close
        reporting fails the first, and dropping the no-progress term from the deadline
        fails the second.

    4. 439a9fb6 updated to dac7fa90index 377df96f

      2 source commits

      1. a3866c57
        Problem: A lost handshake datagram stalls the connection until it times out

        Flyology.QUIC.Connections exposes loss recovery only for the application
        packet-number space. The Initial and Handshake spaces track nothing they
        have sent, discard the peer's ACK frames after parsing them, and never
        acknowledge an ack-eliciting Initial or Handshake packet, which RFC 9000
        13.2.1 requires immediately. Nothing arms the RFC 9002 6.2 probe timeout
        those spaces need.

        Both HTTP/3 drivers inherit the gap. Start_Connection loops on Receive_One
        until the transport connects and Serve_Connection waits up to
        Handshake_Timeout for progress; neither retransmits its own flight. A single
        dropped client Initial or dropped server flight therefore costs the caller's
        whole deadline rather than one probe timeout, which is how an ordinary
        transient loss became a hard CI failure in the raw handshake lane of
        tests/http3_server_integration.adb. That lane now works around the gap by
        resending its own flight; the gap itself is still open.

        Solution: Give the Initial and Handshake spaces RFC 9002 loss recovery

        Each space now owns a sent-packet ledger and retains the CRYPTO ranges it
        has sent in Crypto_Flight, so a probe can rebuild a range under a fresh
        packet number rather than resending a packet QUIC forbids repeating. Peer
        ACK frames drive Sent_Packet_Policy.Apply_ACK and yield the delivery, loss,
        and RTT events the spaces previously threw away. Every packet a space builds
        carries the acknowledgment it owes, and a datagram that produces no response
        sends an ACK-only packet, so a peer's probe timeout clears within one round
        trip.

        Connection_Driver holds one path-wide Recovery_Policy state for both spaces:
        a single probe count backing off together, and a probe timeout that excludes
        max_ack_delay because handshake packets are acknowledged immediately.
        Has_Recovery_Timeout, Recovery_Deadline, and Process_Timeout now report the
        earlier of the handshake and application deadlines, and an expired handshake
        timeout retransmits every unacknowledged CRYPTO range. A client whose peer
        has not completed address validation sends the 6.2.2.1 anti-deadlock probe
        instead. Progress that can only follow delivery of a flight retires it
        without waiting for an ACK.

        The HTTP/3 drivers needed almost nothing. Both already bounded each receive
        by Recovery_Deadline and processed an expired timer, so widening the timer to
        cover the handshake spaces made their loops retransmit; Start_Client gained a
        defaulted Now so the timer has an anchor.

        The raw QUIC lane of the server integration test carried a stand-in for this
        gap: it retained the last flight it sent and resent it when a receive expired,
        because nothing below the test retransmitted. The transport owns that now, so
        the lane drives Process_Timeout against its own clock and the retained flight
        is gone. Its listener sizing and the patience of its response loop are
        unchanged, since neither depended on the missing timeout.

        Handshake-space congestion is accounted but never gates a send: the flight
        is far below the initial window and RFC 9002 permits probing regardless.
        Immediate acknowledgment costs one extra packet per silent datagram,
        including a padded client Initial ACK when only the ServerHello arrives;
        that is what lets a peer stop retransmitting after one round trip.

        Two new tests cover the loss. A deterministic transport test drives an
        explicit clock through a dropped client Initial, a dropped server Handshake
        flight, and the anti-deadlock probe, checking the exact first deadline, the
        doubled backoff, and that an already-acknowledged Initial flight is not
        retransmitted. An end-to-end test puts the routed server and the standard
        client either side of a UDP relay that swallows one flight; with the probe
        timer disabled it stalls for the full deadline and fails.

      2. dac7fa90
        Problem: The QUIC pin hides which version dependents need

        The sibling checkout pinned for local development also stood in for the QUIC
        dependency's version, leaving it declared as "*". Local builds resolve through
        the pin and never notice, but the pin cannot cross into the index, so anything
        depending on this crate is free to resolve any QUIC release at all.

        Solution: Declare the version the pin stands in for

        Constrain the dependency to the development line the pinned checkout provides,
        so the same version is selected once the pin is gone.

        Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

    Dependency changes

    • Added flyology_cachelines ~0.1.1-dev
    • flyology_quic * changed to ~0.1.1-dev
    Compare source revisions
    Development update

    flyology_iri 0.1.1-dev

    3 updates: ddbba90d through dac7fa90

    Allocation-conscious URI, IRI, and URL reference parser

    Manifest fields
    origin
    Show all 3 updates
    1. ddbba90d updated to d99490cfindex 510cfcf6

      3 source commits

      1. 1802f1c9
        Problem: Proof and WebSocket qualification depend on manual runs

        SPARK proof regressions and Autobahn conformance failures can go unnoticed because CI does not execute those campaigns. The existing nightly schedule covers other qualifications but not these policy and protocol checks.

        Solution: Gate proofs and schedule Autobahn qualification

        Run the complete QUIC and HTTP proof suite for every CI trigger and add a scheduled matrix for all maintained Autobahn profiles and task lanes, including matched OpenSSL provenance for secure profiles.

      2. 3d0df29f
        Problem: Hosted level-one proofs time out nondeterministically

        The pull request proof job twice exhausts its level-one prover budget on QUIC ACK range obligations, even though the same obligations pass locally. This leaves an otherwise healthy CI run red and makes proof coverage unreliable on hosted runners.

        Solution: Give CI level-two proof effort

        Let both proof scripts accept FLYOLOGY_PROOF_LEVEL while preserving level one as the default for manual runs. Set the CI proof job to level two so hosted provers have enough effort to complete the full QUIC and HTTP campaigns.

      3. d99490cf
        Problem: HTTP benchmark cannot prepare Flyology runtime from worktrees

        The benchmark runner assumes Flyology runtime scripts live in the HTTP project root. Separate Codex worktrees and Alire dependency layouts do not provide that path, so runtime preparation fails before the benchmark can build.

        Solution: Prepare the runtime from the resolved Flyology root

        Resolve Flyology through the shared dependency-root helper and use that root when invoking prepare-rts.sh, preserving explicit, adjacent monorepo, and Alire-provided dependency layouts.

    2. d99490cf updated to 439a9fb6index 6e2db0ef

      30 source commits

      1. 24c1ea29
        Problem: Running routers cannot be reconfigured atomically

        Servers must currently mutate route setup state directly and cannot safely publish coordinated handler, policy, and middleware changes while requests are in flight. Callers also lack stable identities for addressing registered routes and middleware.

        Solution: Publish immutable router generations through stable identities

        Add opaque route and middleware IDs, transactional update operations, stale-writer detection, and single-load atomic generation publication. Exercise replacement and concurrent dispatch behavior, document the runtime and memory tradeoffs, and add the workflow to the server guide.

      2. 5e5aae59
        Problem: Router publication adds a generation indirection

        Every dispatch loads the published generation and then follows a second pointer to reach its immutable configuration. Each successful update also allocates a separate generation holder solely for retention bookkeeping.

        Solution: Publish configuration allocations directly

        Link retained configurations through their own private history field and atomically publish the configuration address. This removes the holder allocation and one dependent request-path load without changing stale-update or lifetime behavior.

      3. 1df8c3a6
        Problem: Retained router generations are linked by raw address

        The retention chain, the publication gate, and the update base all carry
        System.Address, so recovering a configuration needs an unchecked conversion
        from an address-conversion pointer into a pool-specific access type. Router
        initialization also allocates its first configuration in the declarative
        part, where the handler written to release a failed allocation cannot see
        it: an exception raised there propagates without reaching the handler.

        Solution: Link retained configurations through a typed access

        Complete the configuration type from an incomplete declaration and make its
        access type general, so Previous, First_Configuration, the update base, and
        the publication gate all hold access values and the unchecked conversion
        disappears. The address round trip now stays on the published atomic word
        alone. Allocate the first configuration in the statement part so its handler
        covers the allocation it was written for.

      4. 38b98060
        Problem: Direct registration can tear a generation being served

        Add, Add_Middleware, Add_Route_Middleware, Mount, and the two direct setters
        write the currently published configuration in place, and they admit the new
        element before they write it: the count is incremented first. A request that
        races such a registration reads the raised count and then a route with a null
        handler or a middleware entry with a null component, so the pipeline raises
        Constraint_Error. Only the two setters carried a setup-only note, and the
        identity-returning registration overloads carried none.

        Solution: Seal the router at its first dispatch

        Publish a seal word from the first dispatch and refuse every direct
        registration and setter afterwards with Route_Error naming the update path.
        The dispatch cost is one acquire load of a clean shared line, since the store
        happens only while the word is still clear. Fill each route and middleware
        slot before the count admits it so the ordering is sound on its own, and
        state the sealing rule on the router type and the affected operations.

      5. 1fd5ed9b
        Problem: Mounting makes a middleware registration unaddressable

        Mount assigns a fresh identity to every middleware entry it copies into the
        mounted routes, so the identity the application holds for a subrouter's
        component matches nothing in the destination. Remove_Middleware and
        Replace_Middleware then raise while the mounted copies keep running the old
        component, even though both already walk every route chain accumulating
        matches, which only makes sense when one identity can appear in several
        chains. Begin_Update also accepted a mounted generation, and two candidate
        setters skipped the mounted guard the other mutators apply.

        Solution: Carry the source registration identity through a mount

        Copy mounted middleware entries verbatim so one identity names every chain
        that carries the registration. Refuse Begin_Update on a mounted generation,
        which covers every candidate mutator in one place, and add the guard to the
        admission and challenge setters that lacked it. State the mounting rule on
        the identity type, on Remove_Middleware, and in the server guide.

      6. 8244e2fb
        Problem: A stale candidate cannot be rebuilt in the same update

        Commit raises Stale_Update while the candidate is still attached, so
        Begin_Update on that object then raises Program_Error. The documented retry
        loop only works because it declares the update inside the loop; hoisting it,
        which is the obvious way to avoid re-entering the declaration, deadlocks the
        caller into an unusable object. There is also no way to give up on a
        candidate that failed validation.

        The concurrency audit could not fail cleanly either. Its workers park on a
        barrier that a failure before Start never opens, and the join waits for all
        four to finish with no bound, so a setup error hangs the audit until the
        harness timeout instead of reporting. Its assertion also could not tell a
        run that spanned a publication from one that never observed a change.

        Solution: Release a stale candidate and bound the audit

        Release the candidate when Commit rejects it as stale, since its base is gone
        and it can never be published, and leave a validation failure active so the
        caller can correct and commit it. Add Abandon for an explicit discard.

        Rebuild the audit around a cancellable barrier, bounded joins, and a fixed
        publication count chosen odd so the closing request of every worker has one
        correct answer. Workers now record a pre-publication and a post-publication
        observation, so the test proves it spanned a generation change. Cover the
        duplicate-name and ambiguity rejections that candidate Add defers to Commit,
        and the Set_Match, Rename, Set_Middleware_Stage, and admission operations
        that had no coverage at all.

      7. 5e9b0b41
        Problem: Introspection loops can straddle a router commit

        Every introspection operation takes its own acquire load, so a caller that
        reads Route_Count and then describes each index reads two generations. A
        commit that removes a route between the two calls makes the last index
        invalid and Describe_Route raises Constraint_Error. The same split affects
        Route_Middleware_Count with Describe_Route_Middleware. A diagnostics endpoint
        enumerating routes therefore fails intermittently on exactly the deployments
        runtime reconfiguration is for, and nothing lets a caller pin a generation.

        Solution: Add a snapshot that pins one generation

        Add a Snapshot that captures the published generation, with the whole
        introspection surface available on it. Route the Router forms and the
        Snapshot forms through shared configuration-level operations so both answer
        identically. Retained generations already outlive any snapshot, so the
        snapshot only holds a reference; its finalization is the hook a later
        reclamation scheme needs.

      8. b345dc6f
        Problem: Retained router generations are neither visible nor releasable

        Commit links every superseded configuration into the router's retention
        chain, and only router finalization frees it. Retention is what keeps an
        in-flight dispatch from reading freed storage, but nothing bounds it and
        nothing reports it: a control plane that commits periodically grows the
        chain for the whole process lifetime with no way to observe the growth and
        no way to release it short of destroying the router.

        Solution: Report retained generations and release them on demand

        Add Retained_Generations so the growth is measurable, and Reclaim to release
        every superseded generation while keeping the published one. Reclaim states
        its precondition plainly: the caller must know that no dispatch is running
        and no snapshot of a superseded generation is live, and that is not checked.
        This keeps the request path free of reader accounting while giving a drained
        server a way to return the memory.

      9. e0a9e1b8
        Problem: Ambiguity checks re-split patterns they already compiled

        Registration compiles each pattern into a Segment_List so dispatch does not
        split it per request, but the ambiguity checks throw that away. Patterns
        Overlap and Specificity both take a String and split it again, so Check_Add
        re-splits every stored pattern on every registration and Commit re-splits
        both sides of every route pair. Add also computed the same split twice, once
        for storage and once for the score. The name-keyed Add_Route_Middleware
        scanned for the name, took an identity, then re-read the router and scanned
        again for that identity, which can report an identity failure for a name
        that does resolve. Name comparisons allocated a String per route inspected.

        Solution: Compare the segments and score each route already carries

        Take a Segment_List in Patterns_Overlap and Specificity, so both the
        registration check and the commit check read the stored segments and the
        stored score. Order the cheap score comparison before the segment walk.
        Compile each pattern once per Add. Resolve the name-keyed middleware
        overload in one pass over one generation. Compare names against the stored
        Unbounded_String instead of converting each one.

        Cover the result with an oracle: for each of eight pattern pairs, assert the
        registration decision and the commit decision are both the expected verdict.

      10. bdcfbc8c
        Problem: The server guide predates the update lifecycle it describes

        The guide still tells applications to bound their update rate when retained
        memory matters, which describes a rate tradeoff rather than growth the
        router now reports and can release. It states that direct registration must
        not run concurrently with dispatch without saying the router enforces that.
        It describes per-call introspection as a snapshot, which is what the new
        Snapshot type actually provides, and it tells a caller to rebuild a stale
        candidate without saying the candidate is already released.

        Solution: Describe sealing, snapshots, and generation retention

        Replace the retention paragraph with Retained_Generations and Reclaim, and
        state Reclaim's unchecked precondition beside the call. Say that the first
        dispatch seals the router and what a later direct registration raises. Add a
        short section for traversing one generation with Take_Snapshot, and record
        that Stale_Update releases its candidate while a validation failure keeps
        one for correction. Every new API mention links its generated GNATdoc entry,
        and all 286 generated-API links on the hand-written pages resolve.

      11. 799995fd
        Problem: A generation can be copied into a dispatch parameter

        Router_Configuration is a large non-limited discriminated record, so RM 6.2
        leaves by-copy or by-reference to the implementation for an in parameter.
        Dispatch_Configuration takes a generation that way, and so does every
        introspection and validation operation that reads one. GNAT passes them by
        reference and the request-path measurements show no copy, but nothing in the
        language requires it. An implementation that chose by-copy would duplicate a
        whole generation, with every route pattern, segment list, and middleware
        name, on each request.

        Solution: Take every generation parameter explicitly aliased

        An explicitly aliased parameter is passed by reference by definition, so
        mark all fourteen Router_Configuration parameters aliased. Every actual is
        already an aliased view reached through a Configuration_Access, so no call
        site changes. The guarantee is now a property of the declaration rather than
        of one compiler's choice.

      12. 977add4a
        Problem: No benchmark isolates dispatch against router reloads

        The published-generation word a dispatch reads and the word a commit writes
        live in the same router object, so a reload can invalidate the line the
        dispatchers are reading. Nothing measures that. The existing benchmark
        servers run over sockets and an external load generator, where connection
        and syscall cost hides an effect this small, and none of them reload the
        router while traffic runs.

        Solution: Add an in-process router reload benchmark

        Drive routed dispatch from worker tasks over an allocation-free in-memory
        transport, with one loader task republishing the configuration at a chosen
        rate, and sweep that rate against otherwise identical traffic. Each worker
        counts on its own stack and reports once at the end, so the harness adds no
        contention of its own to the thing being measured.

        The runner repeats each rate as independent process runs and reports best,
        median, worst, and spread, because code layout changes per link and process
        placement dominates repetition inside one run. Reporting the spread is the
        point: an effect smaller than it cannot be claimed from this harness.

      13. 926fed4b
        Problem: The router's dispatch-read words share a region with writer state

        Every dispatch reads the published-generation word and the seal word. Both
        sit in the same record as First_Configuration and the publication gate,
        which only a commit touches, and nothing in the declaration separates the
        two groups. Whatever layout the compiler happens to produce today is a
        consequence of field order and padding, not a property anyone stated.

        Solution: Place the two dispatch-read words in one interference region

        Group them with Flyology_Cachelines.Padded_Groups, so a dispatch fetches one
        region rather than two and a commit dirties the readers' region rather than
        whatever else landed beside it. The two words have the compatible ownership
        that a group requires: each is read by every dispatch and written only by a
        commit.

        This is not a measured improvement and must not be read as one. A commit
        dirties the readers' region once, not once per dispatch, so the cost follows
        the reload rate rather than the traffic: between 10 and 100 reloads per
        second it is 0.0004% to 0.004% of throughput, four orders of magnitude below
        what the reload benchmark can separate from run-to-run spread. The change is
        made because the layout is then correct by declaration instead of by
        accident. The benchmark now records what it can and cannot resolve, so the
        question is not reopened on the assumption that a measurement is available.

      14. 8cae2c89
        Problem: A stalled package mirror burns a runner instead of failing

        The HTTP/2 qualification job installs its independent peer with a bare
        sudo apt-get update, and no step in either workflow bounds its own runtime.
        When the mirror stops answering, apt-get does not fail; it waits. The step
        waits with it, and the only thing that eventually ends the run is the job
        timeout, or a person noticing.

        On 2026-08-19 that happened three times. Run 32226557711 on main sat on the
        update for the whole 150-minute job budget before the job timeout ended it,
        with nobody watching. Runs 32278682887 and 32294697524 sat there 83 and 64
        minutes before someone cancelled them by hand. The same job finishes in 8 to
        14 minutes when the mirror answers, and the install itself takes 11 seconds
        at the median, so each of those runs spent between four and eleven times the
        job's whole healthy duration waiting on one command. A run that hangs also
        reads as a run that is working: there is no failure to retry, and the
        concurrency group keeps the branch occupied until someone intervenes.

        Solution: Bound every network step, and retry the update that stalls

        Give each step that reaches the network a timeout-minutes bound, sized
        against the slowest healthy observation over the preceding 60 runs rather
        than against a guess, so a step that trips one has stalled rather than run
        slowly. Checking out sources and configuring the index finish in seconds and
        are given 5 minutes; the peer install runs 11 seconds at the median and 5
        minutes at its slowest and is given 15. Installing Alire is given 15 on
        different grounds: every observation of it is a cache hit, so the
        observations bound the cached path and say nothing about a cold toolchain
        download.

        Wrap apt-get update in three attempts, each bounded on its own by timeout,
        because the step bound alone would convert a stall into a failure but not
        into a recovery. A wedged mirror connection now becomes a retry against a
        fresh one, so a single transient failure does not fail the job, and the step
        bound stays a backstop rather than the mechanism that catches the common
        case. Only the update is retried: it is the command that stalled, and it is
        the one here that is safe to interrupt and repeat, since a killed run leaves
        partial package lists that the next run refetches. Retrying apt-get install
        would risk resuming from a half-configured dpkg state to no purpose.

        The same failure mode existed in two other places and is closed the same
        way. The Pages workflow had no job-level timeout at all, so a stall there ran
        to the six-hour GitHub default; both its jobs now carry one, and its fetch
        and install steps carry step bounds. The h3spec download in the HTTP/3
        conformance script used a bare curl -fL, which hangs on a stalled connection
        exactly as apt-get did; it now retries with a per-attempt time limit, which
        the existing checksum makes safe, because a truncated or resumed body never
        survives it.

        Nothing about what is installed or how anything is built or tested changes.
        On a healthy run every bound is untouched and every command runs as before;
        the bounds only decide how a stalled run ends.

        Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

      15. 27a8ee59
        Problem: the component getters and Resolve are unmeasured

        flyology_iri_benchmark times can_parse and parse_href over the pinned URL corpus. Neither reaches a component getter: can_parse constructs nothing, and parse_href consumes only the stored serialization length. The paths that read components back out of an already parsed reference, and Resolve above them, have no benchmark at all, so a change to them can be argued only from reading the code.

        Solution: Add a flyology_bench harness for those paths

        flyology_iri_resolve_benchmark reads all eight components at three reference lengths and resolves the RFC 3986 section 5.4 references against a short and a long base. It carries its own inputs, so unlike benchmark.sh it needs neither the Ada URL checkout nor the pinned corpus. Batches fold a value derived from each result into an accumulator handed to a barrier after the ending timestamp, and each iteration advances to a different input.

        Two builds of one library cannot share a process, so before/after runs join through Flyology_Bench.Baselines, whose fingerprint refuses a comparison across operating system, architecture, compiler, or build mode while deliberately excluding the library revision. scripts/resolve-benchmark.sh selects the release mode the published medians measure and passes it to the binary for that fingerprint. Diagnose and Parse do coexist, so the validation pair is a real paired Compare.

        Requested axes are Process_Resource_Metrics, the portable Darwin/Linux set; the metrics CSV reports each axis's collection status rather than leaving it assumed.

      16. d45630c0
        Problem: Slice copies the whole reference for one component

        Every public component getter reaches the stored serialization through the private Slice helper, which materialized the entire reference with To_String and then returned one range of it. The release objects show that call sited unconditionally and ahead of the zero-span test, so an absent component paid a whole-reference copy and a present one paid two allocations and two copies. Reading a four-character scheme out of a 233-byte IRI copied 233 bytes and then four. Resolve sits directly on top of that and reads Path four times and the base path twice. Remove_Dot_Segments, which runs on essentially every resolution, renormalized its input to one-based indexing through an Unbounded round trip.

        Solution: Copy only the component, and read each path once

        Slice now calls Ada.Strings.Unbounded.Slice, keeping the zero guard ahead of it because an absent component has First = 0 and that subprogram takes a Positive Low. The getters compile to a tail call to that subprogram on the present path and to an eight-byte bounds allocation on the absent one. The returned bounds do not change: GNAT's Slice returns the underlying Low .. High range, which is what the discarded whole-text copy was sliced by. Remove_Dot_Segments renormalizes with a constrained subtype instead of the heap. Resolve hoists the relative path and the base path into locals.

        Release-mode medians on an Apple M3 Max, interleaved before/after/before/after against an unrelated build holding the load average near 25, with the repeated pre-change round as a drift control: reading all eight components falls 41.9% at 44 bytes, 33.5% at 235, and 63.8% at 2,009; resolution falls 22.2% against an 18-byte base and 15.5% against a 233-byte one. The drift control landed within 3% of its own first round. Process_RSS_Change and both page-fault axes read zero on both sides, as expected for churn the allocator reuses within a batch; wall time and thread CPU time are the axes that respond.

        Component tests now name the absent components, since the zero guard is what keeps an absent span away from a Positive parameter.

      17. 4df3c149
        Problem: Resolve builds a Reference its caller may not want

        Resolve ends by parsing its assembled result into a second Reference, a heap serialization plus eight component spans, purely to establish that the bytes are well formed. A caller that stores resolved references as opaque bytes needs exactly that guarantee and none of the spans, and has no way to ask for it.

        Solution: Add a serialization-returning Resolve

        Diagnose establishes the same guarantee without constructing anything, and for URI and IRI it is the same computation Parse performs: both reduce to Analyze's error, and a successful non-web parse stores its input verbatim. Web mode normalizes, so there the normalized serialization is the result and the new form still parses to obtain it. The value equals Image of the Reference the other form returns, which the section 5.4 suite now asserts on every case it already covered.

        The two forms share a private Assemble rather than one calling the other. Composing them the obvious way, with the Reference form parsing the serialization form's result, would make it validate twice and cost it roughly 210 ns it does not pay today.

        Paired Compare in one process, release mode, against a 233-byte base: 821.3 ns/op returning a Reference against 743.4 ns/op returning a String, 9.45% less, 95% CI [1.102, 1.107], winning 100 of 100 sample pairs at an order effect of -0.46%. Isolating the validation step, Diagnose measures 211.2 ns/op against Parse's 270.1. The end-to-end saving exceeds that difference because the serialization form also skips constructing and finalizing the result Reference, not only the parse that fills it. The Reference form's median is unchanged, which is what confirms it kept its single validation.

      18. cfb25efc
        Problem: resolution assembles through a growing Unbounded_String

        Resolve merges and reduces its result by appending to an Unbounded_String, which reallocates on nearly every append, and by calling Remove_Dot_Segments, which builds a second one and returns To_String of it. Segment removal is worse than that suggests: collapsing one "/../" runs a whole To_String followed by a Set_Unbounded_String. None of this is visible in the API, and all of it is on the path of every resolution.

        Solution: Assemble into a String sized from the parsed references

        Merging and dot-segment removal never produce more than the base, the relative reference, and the separators between them, so the serialized lengths of the two parsed references bound the result. Both are real lengths rather than Max_Length, which may be Positive'Last, and both come from parsed references rather than input bytes, because web normalization can expand a relative past what it was written with. A bound above what belongs on the stack takes one exact allocation instead, which keeps a single copy of the merge rather than a rarely exercised second implementation.

        Release-mode paired medians against a 233-byte base: the Reference form falls from 823.2 to 550.4 ns and the serialization form from 743.4 to 466.5, so the change reaches the API every existing caller already uses. Resolution against an 18-byte base falls from 475.8 to 331.0. The public specification is untouched.

        A procedure form writing into a caller-supplied buffer was prototyped against this and measured 4.7% below the serialization form, winning 69 of 100 pairs. That difference is the returned copy alone, which is all the wider API buys once the assembly no longer allocates, so it is not adopted.

      19. 616fdfd5
        Problem: large resolutions overflow the stack and leak on failure

        Assembling into a buffer put four objects proportional to the reference length on the primary stack: the one-based copy of the dot-segment input, the merged path, the prefix taken out of the base path, and the result staged on the way out of the heap branch. The heap branch existed precisely so that a caller raising Max_Length would not put a large buffer on the stack, and then reached the stack anyway through the other three. Resolving a four megabyte base raised Storage_Error where the previous implementation returned a result. The heap branch also freed its buffer only on its two normal exits, so any exception through it leaked the allocation, and neither the bound nor the append guard was safe against wraparound in a body whose release profile suppresses overflow checks.

        Solution: Keep every size-proportional object off the primary stack

        Dot-segment reduction indexes its input through an offset rather than copying it one-based, so the copy is gone rather than moved. The prefix is named by bounds into the base path and written straight into the merged buffer. The merged path takes the same stack-or-heap fork as the assembly buffer, because section 5.2.4 reduces the joined path as one string and the pieces cannot be reduced separately. An extended return builds the result where the caller wants it. Both heap blocks free their allocation from an others handler as well as their normal exits.

        The append guard subtracts rather than adds, so it cannot wrap, and the bound is computed in Long_Long_Integer and rejected unless it fits Natural with room to spare, which also keeps every later index lookahead inside range.

        Resolving against bases of one hundred kilobytes, four megabytes and forty megabytes now all succeed, matching the previous implementation. A differential harness comparing both public forms against a verbatim reimplementation of the previous assembly reports no divergence over 429,208 cases, of which 105,202 raise on both sides.

      20. 18ecffdb
        Problem: the serialization Resolve overloads on result type silently

        Resolve returning String and Resolve returning Reference differ only in what they return. Most calls select between them from context, but a call whose context supplies no type does not: comparing two resolutions with "=", or taking an attribute of one, becomes ambiguous. Both were legal while only the Reference form existed, so an existing caller of the published crate meets a compiler error whose cause is not apparent from the code in front of it.

        Solution: Say so where the operation is documented

        Record the overload, name the two shapes that stop compiling, and give the disambiguation. A qualified expression settles either in place, and naming the result in a constant always works. Keeping the shared name is deliberate: the failure is a compile error rather than a silent change of meaning, and the fix is local to the call.

      21. 2f3df5f8
        Problem: the published resolution figures predate the stack fix

        BENCHMARKS.md carries medians taken before the assembly stopped staging size-proportional locals on the stack, and its comparison between the two assemblies stitches together runs from separate sittings on a host under varying load.

        Solution: Re-measure both assemblies in one interleaved sitting

        Swap the two assemblies in place across four rounds, first arm repeated as a drift control, and report the resolution rows from that. The control landed within 0.4% of itself. Removing the one-based copy from dot-segment reduction moved the figures slightly in its favour, so the buffer assembly now reads 34% below the Unbounded one for both public forms rather than 33%.

      22. 4b7b1d6c
        Problem: Admitting a reference costs a serialization copy

        Can_Parse and Diagnose report whether input parses but not how it
        classifies, so a caller that admits only absolute references -- an RDF
        crate deciding whether bytes are an absolute IRI, say -- has to reach for
        Try_Parse. Try_Parse builds a Reference, and building one stores a copy
        of a serialization that is byte for byte the input the caller already
        holds. The caller reads Kind and drops it.

        Solution: Report the classification without building the reference

        Add Inspect, which runs the analysis Try_Parse runs and reports the
        structural kind alongside the parse error. Analyze works on spans over
        the caller's String, so nothing is stored and nothing is allocated. The
        differential harness now holds Inspect to Try_Parse on both the error and
        the kind across the whole seeded corpus.

        Admitting "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" as an
        absolute IRI:

        allocs bytes ns
        via Try_Parse 1 80 145
        via Inspect 0 0 103
        -100% -100% -29%

        Measured with FLYOLOGY_IRI_BUILD_MODE=release. Both forms were run
        alternately, eight rounds each, and the minimum taken, because the host
        carries unrelated build load. Allocation counts are exact.

      23. bc3e3217
        Problem: Preprocessing copies every URL that needs no preprocessing

        Preprocess removes tab, newline and carriage return by appending the
        surviving bytes to an Unbounded_String one at a time. Almost no URL holds
        any of them, so the ordinary case takes an accumulator, grows it, and
        returns a verbatim copy of its own input.

        Solution: Return the trimmed slice when there is nothing to remove

        Scan first and build only once a byte has to be dropped, which also keeps
        the controlled accumulator out of the common path entirely. The slice is
        slid to one because Input_Offset and the parser below read the result at
        one-based offsets.

        Absolute web URLs that take the WHATWG pipeline rather than the fast
        path:

        allocs bytes ns
        web_slow, before 25 1008 2072
        web_slow, after 23 912 1964
        -8% -10% -5%

        web_idna, before 16 752 1661
        web_idna, after 14 656 1547
        -13% -13% -7%

        Measured with FLYOLOGY_IRI_BUILD_MODE=release. Revisions were built into
        separate worktrees and run alternately, eight rounds each, minimum taken,
        because the host carries unrelated build load. Allocation counts are
        exact.

        WPT URL conformance stays at 919/919 with no mismatches.

      24. bf79ef49
        Problem: Percent-encoding and decoding build their results on the heap

        Encode, Encode_Opaque_Path and Percent_Decode each accumulate into an
        Unbounded_String one character at a time and then copy the whole thing
        out with To_String. That is a heap block, the reallocations that growing
        it byte by byte implies, and one full copy, for a result whose length is
        a pure function of the input. Two of the callers encode a single
        character at a time inside a loop, so each iteration paid all of it.

        Solution: Count the result, then write it into the returned object

        Each function now measures its output in a first pass and fills an
        extended return object in a second. Since the count is exact, the
        returned String is the only storage involved -- no accumulator and no
        working buffer, so nothing is allocated and nothing is copied.

        Sizing a buffer up front was the alternative, but the bound that is known
        a priori is three bytes per input byte, and with Max_Length at one
        mebibyte that reserves three mebibytes on the stack in a crate that does
        not build with -fstack-check. Counting first costs a second pass over the
        input and reserves exactly what the result needs.

        Absolute web URLs that take the WHATWG pipeline rather than the fast
        path:

        allocs bytes ns
        web_slow, before 23 912 1964
        web_slow, after 17 720 1670
        -26% -21% -15%

        web_idna, before 14 656 1547
        web_idna, after 12 592 1449
        -14% -10% -6%

        Measured with FLYOLOGY_IRI_BUILD_MODE=release. Revisions were built into
        separate worktrees and run alternately, eight rounds each, minimum taken,
        because the host carries unrelated build load. Allocation counts are
        exact and do not depend on any of that.

        The corpus benchmark does not move: over the pinned 100,025 URLs,
        can_parse holds at 22 ns minimum and parse_href at 105 against 103, with
        acceptance identical at 99999. That corpus is dominated by URLs taking
        the allocation-free fast path, which never reach either function.

        WPT URL conformance stays at 919/919 with no mismatches, which is the
        corpus that exercises these two functions hardest.

      25. 82106435
        Problem: The API reference links to pages the generator never writes

        Since "The router's dispatch-read words share a region with writer state",
        routing.ads groups its two dispatch-read words with
        Flyology_Cachelines.Padded_Groups. That spec is one of the files the
        documentation build documents, and GNATdoc walks every project in the
        closure that Documentation.Excluded_Project_Files does not name, so the
        private with dragged the cachelines crate in with it. Its two tagged
        types, Fitted_Groups.Grouped_Array and Padded_Groups.Grouped_Array, then
        appeared in the index's tagged-type section, each linked to a page of its
        own -- and GNATdoc writes a page per tagged type only under
        --html-oop-style, which this build does not pass. This crate's own tagged
        types are linked as unit page plus fragment and resolve; those two never
        could.

        The site check reports both as missing targets, so the Pages workflow has
        failed on every push to main since that commit landed and the published
        site is frozen at the last green deploy. CI is unaffected: the two
        workflows fail independently, and only one of them was ever red.

        Solution: Document this crate and nothing else

        Name every dependency in Excluded_Project_Files, beside the Flyology
        runtime that was already there. Excluding cachelines alone would clear the
        two broken links, but the closure walk is why they were reachable at all,
        and the same walk had already put twenty-four pages of QUIC and allocator
        internals into a reference whose own footer reads "Public HTTP API only".
        The index now lists this crate's sixty-two entries, the search index
        carries 2441 names with none from a dependency, and no page outside
        Flyology.HTTP is written.

        Removing those pages breaks no link. Their only inbound references were
        the index entries that go away with them: scanning every website page and
        every generated page for their file names finds nothing else pointing at
        them.

        Each exclusion names its project through the prefix Alire exports for that
        crate rather than a path under FLYOLOGY_ROOT. The Flyology crate vendors
        copies of the cachelines and allocator sources, so the two resolve to
        different build directories, and GNATdoc rejects an excluded file that is
        not the project it loaded -- "unable to resolve project file path", a hard
        error rather than a silent no-op, so naming the vendored copy fails the
        run outright. A bare project name fails the same way.

        Verified with docs/api deleted first, since the workflow builds from a
        fresh checkout and a stale page left behind by an earlier run would hide a
        link the workflow cannot resolve. scripts/build-site.sh, which is what the
        workflow runs, reports "Site check passed: 70 HTML files and 136 total
        files".

        Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

      26. 83db8c4d
        Problem: A discarded QUIC Initial ends the HTTP/3 integration exchange

        The dual-stack overload of Routing.Serve divides HTTP_3_Capacity between the
        address families, so HTTP_3_Capacity => 8 gave each listener four connection
        slots rather than eight. Both client profiles in this test address
        "localhost", which resolves to every loopback family on some hosts, and the
        client's connection race completes a full QUIC handshake on each family
        before it discards the losing lane. Each family therefore admits up to five
        concurrent connections here: two live client profiles, two losing race lanes
        awaiting release, and the raw Initial. Instrumented runs reach four of four
        slots routinely.

        A listener whose registry is full discards an Initial without answering it,
        and no handshake-space probe timeout retransmits one. The raw handshake loop
        compounded that: its receive raised Flyology.IO.Timeout_Error straight out of
        the loop, so the eight attempts were never a retry budget and the first quiet
        interval ended the run. The response loop had the same shape. Sizing a run of
        twenty at each capacity reproduced the failure in nineteen runs at two slots
        per family, seven at three, and one at four, tracking the discarded Initials
        one for one.

        Solution: Retransmit the handshake flight and size the listener for the load

        Retain the last flight sent to the server and resend it when a receive
        expires, spending the attempt budget on eight two-second probes rather than
        one ten-second wait. The response loop keeps its budget for waiting, because
        the server does drive application-space probe timeouts and retransmits on its
        own; sixteen one-second probes stay inside the server's connection age.
        Neither loop now ends an exchange on a single discarded datagram.

        Raise HTTP_3_Capacity to sixteen and record the actual per-family model in
        the comment, so the test stops running its listeners at full occupancy by
        accident. With the retransmission in place the capacity is no longer load
        bearing: at two slots per family, where the previous loop failed nineteen
        runs of twenty, the raw handshake now completes in all twenty.

        This is a test change. The absent handshake-space probe timeout is a real gap
        in the QUIC layer and is not addressed here.

      27. d7d87344
        Problem: A QUIC endpoint cannot close before its handshake completes

        CONNECTION_CLOSE is only reachable through the application space. An endpoint
        that abandons a connection while it still holds Initial or Handshake keys has
        no way to say so, and Build_Application_Close_Datagram's precondition rules it
        out.

        The receiving side is missing too. Initial_Space and Handshake_Space parse a
        peer Transport_Close frame, count it, and discard it. A peer that did somehow
        send one would be ignored, so adding a builder alone would change nothing
        observable.

        Solution: Report a peer close from both spaces and expose a close builder

        Initial_Space and Handshake_Space now carry Peer_Closed and Close_Error in
        their Process_Result and stop parsing at the frame, since RFC 9000 10.2.2 puts
        the receiver into the draining state and the rest of the packet cannot change
        that. Connection_Driver acts on it exactly as it already does for the
        application space: Peer_Closed state, Connection_Closed status.

        Build_Handshake_Close_Datagram builds the outbound half in the highest space
        the connection holds, Handshake once that space exists and Initial otherwise,
        so a peer that reached either level can read it. It carries the transport
        APPLICATION_ERROR code that RFC 9000 10.2.3 reserves for an application close
        that its encryption level cannot express, and leaves the connection Failed
        because an endpoint that has begun closing must send nothing else.

        Initial_Space.Build_Transport_Close_Packet passed a zero minimum packet length
        for both roles, so a client-sent Initial close fell under 1,200 bytes and RFC
        9000 14.1 requires a server to discard it. It now derives the minimum from the
        role, as Build_Crypto_Packet already did. That also corrects the existing
        client Fail_Initial_With_Close path, whose closes were unreadable for the same
        reason.

      28. c041b36d
        Problem: A lane that loses the address-family race abandons its handshake

        For HTTP/3 both lanes of the address-family race run Start_Connection, which
        completes a full QUIC handshake before Race.Choose picks a winner. The loser
        raises Connection_Race_Lost, Close_Candidate runs, and Dispose_Connection sends
        an application CONNECTION_CLOSE only when the transport reached the connected
        state. A lane cancelled mid-handshake never did, so the client closes its UDP
        socket and says nothing.

        The server is left waiting for a handshake that will never arrive. On a bounded
        listener that costs a connection slot for the whole handshake timeout, and a
        peer that repeatedly starts and abandons handshakes can hold every slot.

        Solution: Send a handshake-space close from the abandoned lane

        Dispose_Connection now picks the close by transport state rather than skipping
        it: an application close when connected, and Build_Handshake_Close_Datagram
        when the connection is still in Client_Initial or Client_Handshake. Both go out
        on the connection's own UDP socket before it closes, and both remain best
        effort, since a disposal path cannot report a send failure to anyone.

      29. fe4a9d4d
        Problem: A silent peer holds a listener slot for the whole handshake timeout

        Serve_Connection waits for QUIC.Is_Connected against one deadline, the absolute
        handshake timeout measured from the connection epoch. A peer that sends an
        Initial and then stops answering is indistinguishable from one that is merely
        slow, so its worker waits out the full budget and its Connection_Registry slot
        stays taken. A cooperative peer now sends a close, but a crashed, partitioned,
        or hostile one still does not.

        Solution: Deadline an unconnected peer on no progress as well as elapsed time

        Connection_State records the arrival of each inbound datagram, and the
        pre-handshake wait takes the earlier of the absolute handshake deadline and
        that arrival plus Handshake_Idle_Timeout. The absolute budget still bounds a
        peer that keeps sending; the no-progress budget reclaims the slot from one that
        stops.

        Default_Handshake_Idle_Timeout is three seconds. Handshake retransmission on a
        lossy path arrives well inside that window and counts as progress, so only a
        silent peer reaches it. Serve_Listener and both Serve overloads take an
        override. Routing.Serve is left alone: it gets the shorter reclamation from the
        default without adding a parameter to eight overloads.

      30. 439a9fb6
        Problem: Nothing checks that an abandoned handshake frees its listener slot

        Both reclamation paths, the peer's transport CONNECTION_CLOSE and the server's
        no-progress deadline, are only observable as the absence of a stall. No test
        saturates a bounded listener with half-open handshakes, so either could regress
        into the ten-second wait it replaced without a failure anywhere.

        Solution: Saturate a listener of capacity N and require a fresh Initial

        http3_handshake_abandon runs two phases against a capacity-three listener whose
        handshake timeout is twenty seconds, far beyond every deadline it asserts, so a
        slot reclaimed inside one of them cannot be explained by that timeout. Each
        phase fills every slot with a handshake that will not complete, asserts that a
        further probe is refused, releases the lanes, and then requires a fresh Initial
        to be admitted.

        The first phase abandons with closes and leaves the no-progress deadline out of
        range; the second goes silent and relies on the deadline alone. Odd lanes
        consume the ServerHello first so they abandon from the Handshake space, while
        even lanes abandon from the Initial space, covering both protection levels. The
        probe repeats its Initial while no worker answers, the way a real client's probe
        timeout would, so a slot released partway through the budget is still taken up.

        Each phase was confirmed to fail on its own: removing the driver's peer-close
        reporting fails the first, and dropping the no-progress term from the deadline
        fails the second.

    3. 439a9fb6 updated to dac7fa90index 377df96f

      2 source commits

      1. a3866c57
        Problem: A lost handshake datagram stalls the connection until it times out

        Flyology.QUIC.Connections exposes loss recovery only for the application
        packet-number space. The Initial and Handshake spaces track nothing they
        have sent, discard the peer's ACK frames after parsing them, and never
        acknowledge an ack-eliciting Initial or Handshake packet, which RFC 9000
        13.2.1 requires immediately. Nothing arms the RFC 9002 6.2 probe timeout
        those spaces need.

        Both HTTP/3 drivers inherit the gap. Start_Connection loops on Receive_One
        until the transport connects and Serve_Connection waits up to
        Handshake_Timeout for progress; neither retransmits its own flight. A single
        dropped client Initial or dropped server flight therefore costs the caller's
        whole deadline rather than one probe timeout, which is how an ordinary
        transient loss became a hard CI failure in the raw handshake lane of
        tests/http3_server_integration.adb. That lane now works around the gap by
        resending its own flight; the gap itself is still open.

        Solution: Give the Initial and Handshake spaces RFC 9002 loss recovery

        Each space now owns a sent-packet ledger and retains the CRYPTO ranges it
        has sent in Crypto_Flight, so a probe can rebuild a range under a fresh
        packet number rather than resending a packet QUIC forbids repeating. Peer
        ACK frames drive Sent_Packet_Policy.Apply_ACK and yield the delivery, loss,
        and RTT events the spaces previously threw away. Every packet a space builds
        carries the acknowledgment it owes, and a datagram that produces no response
        sends an ACK-only packet, so a peer's probe timeout clears within one round
        trip.

        Connection_Driver holds one path-wide Recovery_Policy state for both spaces:
        a single probe count backing off together, and a probe timeout that excludes
        max_ack_delay because handshake packets are acknowledged immediately.
        Has_Recovery_Timeout, Recovery_Deadline, and Process_Timeout now report the
        earlier of the handshake and application deadlines, and an expired handshake
        timeout retransmits every unacknowledged CRYPTO range. A client whose peer
        has not completed address validation sends the 6.2.2.1 anti-deadlock probe
        instead. Progress that can only follow delivery of a flight retires it
        without waiting for an ACK.

        The HTTP/3 drivers needed almost nothing. Both already bounded each receive
        by Recovery_Deadline and processed an expired timer, so widening the timer to
        cover the handshake spaces made their loops retransmit; Start_Client gained a
        defaulted Now so the timer has an anchor.

        The raw QUIC lane of the server integration test carried a stand-in for this
        gap: it retained the last flight it sent and resent it when a receive expired,
        because nothing below the test retransmitted. The transport owns that now, so
        the lane drives Process_Timeout against its own clock and the retained flight
        is gone. Its listener sizing and the patience of its response loop are
        unchanged, since neither depended on the missing timeout.

        Handshake-space congestion is accounted but never gates a send: the flight
        is far below the initial window and RFC 9002 permits probing regardless.
        Immediate acknowledgment costs one extra packet per silent datagram,
        including a padded client Initial ACK when only the ServerHello arrives;
        that is what lets a peer stop retransmitting after one round trip.

        Two new tests cover the loss. A deterministic transport test drives an
        explicit clock through a dropped client Initial, a dropped server Handshake
        flight, and the anti-deadlock probe, checking the exact first deadline, the
        doubled backoff, and that an already-acknowledged Initial flight is not
        retransmitted. An end-to-end test puts the routed server and the standard
        client either side of a UDP relay that swallows one flight; with the probe
        timer disabled it stalls for the full deadline and fails.

      2. dac7fa90
        Problem: The QUIC pin hides which version dependents need

        The sibling checkout pinned for local development also stood in for the QUIC
        dependency's version, leaving it declared as "*". Local builds resolve through
        the pin and never notice, but the pin cannot cross into the index, so anything
        depending on this crate is free to resolve any QUIC release at all.

        Solution: Declare the version the pin stands in for

        Constrain the dependency to the development line the pinned checkout provides,
        so the same version is selected once the pin is gone.

        Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

    Compare source revisions
    Development update

    flyology_numa 0.1.0-dev

    4 updates: 9a24bf68 through a53da35d

    Memory-node topology reporting for Ada

    Manifest fields
    origin
    Show all 4 updates
    1. 9a24bf68 updated to 60de2c69index 8a8e9de5

      1 source commit

      1. 60de2c69
        Problem: A development pin ships in the published manifest

        flyology.gpr imports flyology_allocators.gpr, and the manifest both declares
        flyology_allocators as a dependency and pins it to the in-repo directory.
        Alire honours pins only in a root crate's manifest, so a consumer resolving
        flyology from the index never receives that dependency. Its solution omits
        flyology_allocators entirely and gprbuild then fails with "imported project
        file flyology_allocators.gpr not found". A crate whose only dependency is
        flyology = "~0.1.1-dev" reproduces it in two lines.

        Nothing in this repository reports the fault, because the pin satisfies the
        dependency for every build performed here. The pin also hid two further
        assumptions that only the in-repo directory could satisfy.

        Solution: Resolve the allocators dependency from the index

        Drop the pin so the declared dependency resolves the same way for this crate
        and for its consumers. The published flyology_allocators 0.1.0-dev is built
        from this repository at the same commit and the same subdirectory, so the
        source reached is identical; only the path by which it is reached changes.

        Configure the organization index in this repository's own workflows. They
        carried the community index alone, because the pin meant no job here ever
        resolved flyology_allocators from an index, and it is published only in the
        organization index. Without that step alr reports an incomplete solution
        naming flyology_allocators as missing.

        Name the excluded documentation project through the imported project rather
        than through a repository path. Documentation.Excluded_Project_Files listed
        flyology_allocators/flyology_allocators.gpr, which resolved only while the
        crate sat in this working tree; as a dependency its project lives in the
        Alire build tree under a content hash. Flyology_Allocators'Project_Dir asks
        the imported project where it is, so the exclusion holds wherever the
        dependency is deployed and the allocator packages stay out of this crate's
        generated API, where they would otherwise be documented twice.

        Record the rule that produced the fault in the agent guide: no committed
        pins in a crate manifest, alr pin in the consuming workspace for unpublished
        work, and a declared dependency must resolve from the index. Name the
        gprbuild error there too, since that is where the fault appears and it names
        a project file rather than a crate.

    2. 60de2c69 updated to 9782c81bindex 75a836be

      16 source commits

      1. aeb10612
        Problem: The site does not list Flyology RDF

        The hero project map, the standalone catalogue, the library ledger, and
        llms.txt each name every component. Flyology RDF publishes a website, a
        guide, and three generated API references at rdf.flyology.org, but the name
        appears nowhere in this repository. A reader who arrives at the site and
        looks for what Flyology offers does not learn that the project exists.

        Solution: Add the project to the hero map, catalogue, ledger, and llms.txt

        flyology_rdf depends on flyology_iri only. It needs no runtime preparation
        and starts no tasks, so it belongs with the standalone libraries. Every list
        keeps its alphabetical order, so the entry sits between Flyology NUMA and
        Flyology SIMD and the ledger indices shift from S07..S08 to S08..S09.

        The ledger and llms.txt entries carry all three generated references, as the
        Flyology Postgres entries already do, because the project site treats the
        Notation3 and SPARQL APIs as first-class navigation.

        The llms.txt project-structure summary also omitted Flyology Allocators and
        Flyology NUMA, which the same file already listed further down. Both names
        join the summary here.

        Verified with the website-kit site checker, whose output is unchanged from
        the pre-change baseline, and by rendering the pages: the hero, catalogue,
        and ledger all name the project. The six linked URLs return 200.

      2. 2188ee0d
        Problem: The project map announces its framing and then hides the components

        The figure caption claimed "One project, two adoption paths" above two cards
        that already carry the same fact in their labels, so the caption restated
        what the diagram shows. The two card subtitles were not parallel either:
        "Core component" named a role while "No runtime dependency" named a
        dependency, so neither pair member helped a reader compare the paths.

        The component names below them were plain list items. A reader who found the
        name that matched the problem had no way to reach the component from the
        diagram and had to scroll to the catalogue to find the same name again.

        Solution: Drop the caption, make the subtitles parallel, and link the names

        The subtitles now read "Prepare the runtime" and "Add a crate", which state
        the two adoption paths as the actions they are. The figure keeps an
        accessible name through aria-label, and the figcaption rule leaves the
        stylesheet with the element it styled.

        Each component name becomes a link to its best available destination, which
        is the destination the catalogue below already uses: the project site where
        one exists, then the guide, then the generated API, then the source tree.
        The pill moves from the list item to the anchor so the whole badge is the
        hit target. Links open in a new tab and carry no underline, as requested, so
        hover brightens the border and adds a faint fill instead. Each list states
        the new-tab behavior once in its aria-label rather than repeating it in
        twelve hidden spans.

        Verified by rendering the page: every badge computes text-decoration-line
        none and cursor pointer, and the hovered badge is distinguishable from its
        neighbors. The site checker reports one new line against the baseline,
        api/flyology_debug/ from the new Debug badge, which resolves once
        scripts/docs.sh generates the GNATdoc output that this partial build omits.

      3. 5dfd5d36
        Problem: Nothing coordinates tools that need exclusive CPU capacity

        Two measurement runs that share a machine produce two wrong answers, and
        neither run can tell that it happened. The problem is not confined to
        benchmarks: a load generator, a soak test, or a profiler makes the machine
        loud, and a benchmark needs it quiet. Both want the same thing from opposite
        directions, and nothing lets them find each other.

        Worse, two runs that each suspend collection when they detect interference
        are symmetric controllers observing each other. Each pauses because the other
        is loading the machine, both then observe quiet, both resume together, and
        both immediately pause again.

        Solution: Specify a host CPU lock convention and implement it

        The convention is named for the resource rather than for benchmarking, so
        that the tools which create load take the same claim as the tools which need
        its absence. Conflict detection is flock and nothing else: liveness is the
        lock itself, so a holder that dies releases with no cleanup path, no stale
        registry entries, and no pid-reuse hazard.

        A machine-wide claim takes LOCK_EX on the claim file; a claim on individual
        CPUs takes LOCK_SH there and LOCK_EX on one file per CPU. Disjoint core-scoped
        claims therefore proceed concurrently while a machine-wide claim excludes them
        all, with no registry and no arbiter. Per-CPU claims are acquired in ascending
        order, because a total order is what stops two callers with overlapping sets
        from deadlocking on each other's partial claims.

        The path is a single deterministic default rather than a writability-probing
        fallback chain. A chain reintroduces the failure it was meant to prevent:
        /run/lock is 1777 on Debian and root-owned 0755 on Red Hat derivatives, so a
        root process and an unprivileged process on one machine would probe
        differently, land on different files, and each conclude it holds the machine.
        $TMPDIR is avoided for the same reason, being per-user on macOS.

        File content is diagnostic and is never consulted to decide conflicts. It is
        still specified and parseable, one key=value pair per line, because a reader
        must be able to name the holder; cwd is included because tool and pid alone do
        not distinguish one checkout or CI workspace from another. Readers open the
        file without locking, since a shared lock would block behind the very holder
        they are trying to identify, and must tolerate content that is empty, stale,
        or half-written.

        A claim is not proof of exclusivity, and the implementation does not present
        it as one. systemd PrivateTmp= bind-mounts a per-service directory over /tmp,
        so two services share every CPU and cannot see each other's claim files; that
        case is detected from /proc/self/mountinfo and reported as namespace-scoped.
        Separate containers are not detectable from inside and need an explicit shared
        path. A path can be proven private but never proven machine-wide.

        Only the C macros live in the native unit. GNAT's C_Variadic_2 convention
        calls open() correctly even on Darwin/AArch64, where variadic arguments are
        passed differently from fixed ones, so the protocol, the file grammar, and the
        /proc reader are all Ada. The convention compiles on every GNAT this crate
        supports, checked against 13.2.2 through 16.1.0 against an alire.toml floor of
        13, so no compatibility shim is carried.

        Verified by building the crate, and by taking claims on disk: the file matches
        the published grammar, parses with awk -F=, is created 0666, and per-CPU files
        are named beside the machine file.

      4. 13b71a5b
        Problem: The CPU gate only proves the host was quiet before warmup

        CPU_Quiescence samples host counters once, before clock characterization, and
        then never looks again. A machine that goes busy halfway through collection
        produces a result that reads as clean, and nothing in the measurement, the
        console card, or the machine-readable output says otherwise. The gate's own
        documentation admits it "cannot prevent new load from arriving after
        collection begins", and until now that was the end of the story.

        The obvious repair is not available either. Host utilization cannot simply be
        compared against a limit during collection the way the preflight does it,
        because by then the benchmark thread saturates a core and every sample would
        trip the limit.

        Solution: Watch for foreign load during collection and say what was found

        Foreign load is host busy time minus this process's own CPU time, so load the
        benchmark itself creates is correctly not foreign. The estimate scales the
        host busy ratio by wall time rather than converting ticks, so the platform
        tick length never enters the arithmetic. Cross-checked against top on a loaded
        machine, the two agree to within 0.1 percent.

        Three responses form a ladder. Observe records and keeps everything. Retake
        discards the contaminated window and collects it again. Pause waits for the
        host to settle, re-warms, and then collects it again. The re-warm is not
        politeness: a resumed run has cold caches, predictors, and frequency state, so
        without it the first sample after a pause is the outlier the pause existed to
        avoid.

        Nothing adjusts a reported statistic. A skew factor derived from observed load
        would be invented data, because the cost of interference depends on whether
        the contention is an SMT sibling, a shared cache, memory bandwidth, or another
        socket, and the same foreign share can mean no slowdown or a large one. Runs
        are annotated or repaired, never corrected.

        Observation happens between timed samples over windows of whole collection
        units, where a unit is one sample, one comparison pair, or one balanced
        multi-way round. A response therefore never splits the two halves of a pair
        and never lands mid-round, where it would spread interference unevenly across
        the cases a round exists to compare fairly. Windows carry a margin over the
        configured minimum: sized to only just reach it, ordinary batch jitter drops
        them below it and they silently degrade to observation. Host counters are
        tick-based, so a window that still falls short is recorded but never acted on.

        Discarding a window rolls back what the window changed. Per-sample values are
        written by index and survive a retake intact, but the position tally of a
        comparison pair and the process-telemetry summaries are running sums, so a
        discarded pass gives them back. Without that, a run with eighteen retained
        samples and twenty-four retakes would report elapsed time and an average CPU
        share covering forty-two samples, most of which were thrown away.

        Budgets degrade rather than abort. An exhausted retake or pause budget
        continues under Observe and reports it, and paused time is excluded from
        Maximum_Sampling_Time because waiting for the host is not collection.

        Placement is optional and sharpens attribution: with a strict binding every
        other CPU's busy time is foreign outright, and the placed CPU's share is its
        busy time minus the placed thread's own. SMT siblings join the watched set,
        because a process saturating the sibling of the placed CPU slows the
        measurement while leaving the placed CPU's own share clean, which makes
        sibling-blind core-scoped observation worse than host-wide observation rather
        than better. Placement is Linux-only in practice; Apple Silicon implements no
        thread affinity and rejects every request, so the Host_Control documentation
        no longer describes Darwin placement as merely advisory.

        Placement binds only the calling thread, so another thread of this process can
        occupy a watched CPU, where its time is indistinguishable from foreign load.
        Each window therefore reads process CPU as well as thread CPU, and their
        difference bounds how much of the watched capacity those threads could account
        for. Once that bound exceeds the configured foreign limit, the core-scoped
        answer can no longer address the question the limit asks: the run drops to
        host-wide observation, which is well defined for a multi-threaded process, and
        reports Attribution_Diluted. Otherwise a scheduler benchmark run under
        placement would spend its retake budget discarding samples over load it
        created itself. The window that reveals the dilution is discarded rather than
        recorded, because its value was computed under the attribution being
        abandoned.

        The direction of that fallback is deliberate. Core-scoped attribution
        subtracts only the placed thread, which over-reports interference when other
        threads share the watched CPUs; subtracting the whole process instead would
        deduct time our threads spent on CPUs outside the watched set, under-report
        foreign load, and let contaminated data pass as clean. Over-reporting shows up
        in the retake and contamination counts; under-reporting shows up nowhere.

        The host CPU claim is taken before the preflight gate, since waiting for a
        quiet host and then blocking on the claim leaves the quiet verdict stale.

        Everything observed reaches the console card, the CSV schema, and the JSON
        object. That visibility is the point: a run that had to repair itself must say
        so, or a heavily repaired result reads as a quieter machine than the one it
        ran on.

        Verified with ./scripts/test.sh on Darwin/aarch64 and in an Ubuntu 24.04
        container on Linux/aarch64, and under qemu-system-aarch64 across four CPU
        topologies. Core-scoped attribution asserts that it closed an observation
        window, so the thread-CPU probe it depends on cannot fail silently. Two
        assertions were checked against builds that defeat them: one with sibling
        collection disabled fails the sibling assertion under cores=2,threads=2 and
        passes without SMT, and one with the dilution check disabled fails the
        fallback assertion while a task of the test's own process burns CPU. Retake
        and pause are driven by a spawned process, because load raised inside this
        process is its own CPU time and is subtracted by design.

      5. 845bdaca
        Problem: The new guide section ignores the site's writing rules

        website/AGENTS.md governs hand-written pages under guide/**. The interference
        section met none of its API-link requirements and several of its style rules.

        Every public entity it introduced went unlinked: Interference, Placement,
        Host_Lock, the three Interference_Response literals, Maximum_Retakes, Window,
        Rewarm_Time, Maximum_Foreign_CPU_Percent, Include_Siblings, Require_Strict,
        Attribution_Diluted, and Environment. The same page already links
        CPU_Quiescence, Stable_Time, and Timeout, so the new section also read
        inconsistently against its own neighbours.

        Solution: Link the API entities and apply the three prescribed reviews

        The three reviews ran in sequence and are labelled here, since separate review
        agents were unavailable.

        Technical. "Foreign load is host busy time minus this process's own CPU time"
        held only without placement, because core-scoped attribution subtracts the
        placed thread rather than the whole process; the sentence now says so, and the
        placement paragraph states which CPUs the harness measures. "The re-warm is
        required" overstated a configurable field, so the text names Rewarm_Time and
        says what a zero value leaves behind. "When the difference exceeds the
        configured limit" named neither the limit nor the compared quantity, which
        also left Maximum_Foreign_CPU_Percent unlinked. Two harnesses that both pause
        do not deadlock as claimed; they alternate between pausing and resuming.

        Editorial. "This matters most" and "Without it" both referred back to
        something unnamed. Both now name their subject.

        Controlled language. "Sharpens attribution" was figurative and is now
        "narrows attribution to the placed CPU and its SMT siblings". "A run that
        repaired itself reports that fact" personified the run; the report is the
        actor, and it states counts.

        Verified with ./scripts/build-site.sh and the site checker, which passes 144
        HTML files. All fourteen API links resolve to an existing anchor in the
        generated GNATdoc output, and each target matches the entry the API search
        index gives for that entity. No sentence in the section exceeds the 25-word
        review signal.

      6. edf788ef
        Problem: The guide does not say the host controls are opt-in

        The interference section described three capabilities without saying that a
        run acquires none of them unless it asks. BENCH 07 states that contract for
        the preflight gate, and the page marks the default value of a choice where one
        exists, as it does for Equal_Time and Balanced_Rounds. The new section did
        neither, so a reader could not tell that enabling the watch alone changes
        nothing about the collected data.

        The claim file was also absent. The page named three environment variables but
        not the one path that other tools must agree on, leaving the coordination
        surface a click away in the convention document.

        Solution: State the defaults, the claim path, and the budget interaction

        Observe is now marked as the default response, in the form the page already
        uses. The closing paragraph mirrors BENCH 07: the watch, placement, and the
        host claim are disabled by default, so an existing run acquires no new wait or
        failure condition. The opening sentence calls the watch optional where the
        reader first meets it.

        The claim paragraph names /tmp/host-cpu.lock, the Path field that overrides it
        for one run, and the HOST_CPU_LOCK_PATH variable that overrides it for every
        tool following the convention. An earlier draft named only the variable, which
        implied it was the sole override; the technical review caught that against
        Resolved_Path and Try_Acquire.

        The Window row gains the limit that qualifies it. A window covers whole units,
        so a window spanning many short samples can exceed Maximum_Retakes on its
        first discard. Collection then continues under Observe and reports the
        exhausted budget, which otherwise looks like the response never ran.

        Numeric field defaults are deliberately not repeated here. No other section of
        the page tabulates them, every field now links to its generated entry, and a
        duplicated value is one that can go stale.

        Verified with ./scripts/build-site.sh and the site checker, which passes 144
        HTML files. All fifteen API links resolve to an existing anchor, and each
        target matches the entry the API search index gives for that entity, including
        the ambiguous Path simple name, which resolves to Host_Lock_Policy.Path. No
        sentence in the section exceeds the 25-word review signal, and no entity is
        linked twice.

      7. 4fbe5020
        Problem: The recording smoke test separates its workloads with a delay

        recording_smoke drives two benchmarks from four tasks and asserts that the
        slow benchmark's recorded median wall time exceeds the fast one's. The
        separation comes from delay 0.000_2 against delay 0.000_8. A relative delay
        is rounded up to the host timer tick, and on a Linux kernel with a coarse
        tick both requests wake at the same boundary near 3 ms. A four-task probe
        with no recorder involved shows the first iteration of each task honoring
        the request and every later one landing on the same plateau:

        0.0002 s: 323 3710 2829 2972 3069 2947 ... (us)
        0.0008 s: 1167 3307 2482 3625 2793 3045 ... (us)

        The two recorded medians then arrive at 2.98 ms and 2.99 ms, ordered by
        scheduling noise alone. On Ubuntu 24.04 with GNAT 16.1.0 on aarch64 the
        assertion fails about half the time: 9 of 20 runs on a clean checkout. macOS
        resolves the two delays apart, which is why the test has held there. The
        independent comparison checked two assertions below rests on the same
        separation and fails with it.

        Solution: Separate the distributions by work the workers perform

        Each worker spins a volatile rotate-and-xor accumulator, 20_000 rounds for
        the fast benchmark and twenty times that for the slow one, the idiom the
        file's concurrent PMU-session block already uses. That is roughly 33 us
        against 680 us, a twentyfold gap read by a nanosecond wall clock, so no
        timer resolution enters the measurement. It also costs less than the
        sleeping it replaces: the slow workers take about 14 ms rather than 60 ms.

        The assertion stands, since the ordering is the invariant worth holding, but
        its message now carries both medians so a failure on an unusual host reports
        numbers rather than a verdict.

        Verified on the failing environment, an Ubuntu 24.04 container with GNAT
        16.1.0 on aarch64: 30 of 30 runs pass where HEAD fails 9 of 20 in the same
        container, 20 of 20 under a two-CPU quota, and 10 of 10 with 24 competing
        spinners on that quota. scripts/test.sh passes three times from a fresh
        source export there and once on macOS. A calibration probe over 105 further
        trials across those CPU configurations held the ratio between 14x and 30x
        with no inversions and Relative_Change_Percent positive throughout.

      8. ae5b52d7
        Problem: A group snapshot cannot say whether its event loop is busy

        Flyology.Observability.Group_Snapshot carries thirty fields covering queue
        depths, wait categories, and cumulative counters, but none of them reports how
        much of an event loop's time was spent doing work. Pool imbalance is therefore
        invisible from outside the process: a group with a deep ready queue and a group
        that is idle produce the same evidence once their momentary queue depths match.
        Made_Progress detects a stalled loop but not a saturated one, and its comment
        already records why a per-dispatch clock read was rejected as the answer.

        Solution: Time the poller wait a loop takes when nothing is ready

        An event loop enters Wait_Batch only when its ready queue is empty, so the idle
        path is both the exact complement of the loop's working time and a path a busy
        loop never repeats. The scheduler stamps the wait before releasing the group
        lock and closes it after reacquiring, keeping the in-progress wait in the group
        so an observer adds it rather than charging a long block as busy time. Nothing
        is added to dispatch, context switch, or any other hot path.

        Group_Snapshot gains Uptime_Nanoseconds, Idle_Nanoseconds, and Idle_Waits, and
        the runtime snapshot ABI moves to version 6. Idle time is clamped to uptime and
        both come from one clock reading, so callers can always take the difference or
        the ratio. tests/native/process_lifecycle_probe.c pins that ABI and its layout,
        and moves with it.

        The cost is measured rather than asserted. runtime_callback_bench adds
        poller_idle_cycle for the instrumented path and monotonic_clock_read for the
        unit of work it adds; benchmarks/idle_wait_rate reports the rate a loop
        actually reaches, because the effect is far below what a differential timing
        run resolves on this host. On macOS/AArch64 a reading costs about 20 ns, a
        socket ping-pong reaches roughly 32,000 to 38,000 waits per second per loop,
        and a loop doing nothing else reaches roughly 120,000 to 160,000: under 0.2%
        and under 0.7% of a loop's time respectively.

        Checks run: ./scripts/test.sh (pass, including the new
        observability_utilization_smoke), ./scripts/docs.sh (pass, no new warnings),
        ./scripts/bench-runtime.sh.

      9. 6c4bfc3c
        Problem: The guide cannot tell a reader whether a group is busy

        Step 10 of the guide lists the readings that diagnose a group, but every one of
        them describes queue contents. A reader who wants to know whether an event loop
        is saturated has no entry to follow, and the utilization fields the runtime now
        publishes appear only in README.md and the generated API reference.

        Solution: Document loop utilization where the guide diagnoses a group

        A new subsection explains what the runtime measures, why the subtraction is
        always valid, and the two readings that look alike: a group whose tasks all
        wait resembles a group with nothing to do, and a task that never suspends keeps
        its loop out of the poller and reports as fully busy. A decision row places the
        measure next to the queue-depth readings it qualifies. The cost paragraph names
        the measured figures and the script that reproduces them, rather than asserting
        that the accounting is cheap.

        The worked example is compiled and run by tests/guide_utilization_example.adb.
        The first draft of that example did not compile, because Counter is a modular
        subtype and the subtraction needs a use type clause the guide had not shown. A
        test main is the only check that keeps a printed example honest about the
        visibility a reader must supply.

        Checks run: ./scripts/test.sh (pass, including the new
        guide_utilization_example), ./scripts/build-site.sh, and check-site.mjs over
        the built site as CI runs it.

      10. fb881640
        Problem: The utilization copy states a rule that does not hold

        The website/AGENTS.md technical review is required for any changed capability,
        limit, or timing claim, and running it on the new guide section found four
        faults.

        Two are wrong rather than unclear. The guide told a reader that `Counter` needs
        a `use type` clause because the subtype is modular; the clause is needed
        because the operators of a type declared in another package are not directly
        visible, so the stated rule teaches the wrong thing. The guide also said an
        event loop waits in its poller only when no task can run, but the loop polls
        with a zero timeout while work is ready, and the same section counts that
        polling as busy time.

        The remaining two narrow a claim that had become broader than the code.
        "Dispatching, polling with work ready, or running task code" reads as an
        exhaustive account of a loop's busy time and omits timer promotion, file
        submission, and cancellation processing. That wording appeared in the guide,
        README.md, and the Group_Snapshot field documentation, so all three change
        together. `Group_Snapshot` and `Snapshot` appeared only inside the code block
        and were linked nowhere in prose, which the API-link rule does not allow.

        Solution: Correct the two faults and narrow the two broad claims

        The editorial and controlled-language passes contributed three further changes:
        one repeated paragraph opening, "idle fraction" used before the section
        introduces it, and "reading" carrying both a clock read and a snapshot.

        Checks run: ./scripts/docs.sh (pass, no new warnings),
        ./scripts/build-site.sh with check-site.mjs over the built site,
        and observability_utilization_smoke, guide_utilization_example, and
        observability_smoke rebuilt and re-run.

      11. bca8ad7f
        Problem: Previewing the built site needs an ad-hoc server command

        scripts/build-site.sh writes the complete site to build/site, but nothing
        records how to serve it. Reading a guide page as it will be published means
        inventing a static-server invocation each time, and picking a port that does
        not collide with a development server already running.

        Solution: Record a launch configuration that serves the built site

        The entry serves build/site on port 8231. It reads the build output and does
        not produce it, so run scripts/build-site.sh first and again after editing
        anything under website/.

        Checks run: served build/site through the entry and loaded the guide page.

      12. 104d406f
        Problem: macOS L1 detection reports efficiency-core capacity

        The macOS body queries the flat hw.l1dcachesize sysctl. On a heterogeneous
        Apple silicon host that name reports the efficiency-core capacity, not the
        performance-core capacity: one 12P/4E host reports 65536 bytes for the flat
        name against 131072 for hw.perflevel0.l1dcachesize. Flyology_Cachelines.
        L1_Data_Cache_Size therefore reports half the performance-core L1d capacity,
        and L1_Data_Cache_Slots derives its slot count from that halved value.

        The reader also assumed every queried name stores a 64-bit value. It read
        each name into one 64-bit object and accepted a short reply, so a 32-bit
        value was correct only because Darwin is little-endian and the object was
        zero-initialized. The per-level names are 32-bit.

        Solution: Prefer the highest performance level and read the reported width

        macOS 12 and later describe a host whose cores are not identical as ordered
        performance levels, where hw.perflevel0 is the highest-performing level. The
        macOS body now queries hw.perflevel0.l1dcachesize and falls back to the flat
        name only on a host that publishes no performance level, such as macOS 11 and
        earlier or an Intel Mac. Querying hw.nperflevels first would add nothing: the
        per-level name exists exactly when the host publishes performance levels.
        Hardware_Cache_Line_Size is unchanged, because Darwin publishes no per-level
        line size and both Apple silicon core types use the same line.

        The public API keeps its Cache_Query_Result surface. Reporting per-level
        geometry is a separate design question, and it should not ride along in a
        detection correctness fix.

        The sysctl reader moves into a new private Flyology_Cachelines.Macos child,
        mirroring the existing Flyology_Cachelines.Linux split between mechanism and
        policy. It requests each name's stored width before reading the value and
        rejects any other width, so a 32-bit name, a 64-bit name, a string, and an
        absent name are all handled without depending on byte order. Failed and
        malformed queries still degrade to Unavailable rather than raising.

        The GNATdoc comments on L1_Data_Cache_Size and L1_Data_Cache_Slots, the crate
        README, and the website cachelines guide now state that a host whose cores are
        not identical reports one core type, and which one each platform reports. A new
        macOS detection test mirrors the Linux one: it exercises the sysctl reader
        directly and checks that the reported capacity is the highest performance level
        the host publishes.

        Checks run: ./flyology_cachelines/scripts/test.sh (the native test now reports
        131072 bytes of L1 data cache on a 12P/4E host, and the new macOS detection
        test passes) and ./flyology_cachelines/scripts/docs.sh (zero GNATdoc warnings).

      13. d3af8647
        Problem: The Linux detection test requires an optional mechanism

        Flyology_Cachelines.Linux_Testing asserts that both Detect_From_Sysconf and
        Detect_From_Sysfs report a value. Only their composition is guaranteed:
        glibc answers _SC_LEVEL1_DCACHE_SIZE and _SC_LEVEL1_DCACHE_LINESIZE from
        CPUID on x86-64, but reports zero on aarch64, where sysfs is the only
        mechanism. Detect already treats sysconf as optional and falls back to
        sysfs, so the test is stricter than the code it covers.

        The test therefore fails on aarch64 Linux with "sysconf cache detection
        failed". CI runs ubuntu-latest on x86-64, where sysconf answers, so the
        failure is invisible there. It reproduces on aarch64 Linux, which AGENTS.md
        tells contributors to prefer on Apple silicon because it is native and
        faster.

        Solution: Require the composition and check each available result

        Run now requires that at least one mechanism reports a value, and checks
        consistency only for a mechanism that reported one. That is what the
        production detector promises: it composes sysconf and sysfs, and returns
        Unavailable only when neither answers.

        Checks run: the crate suite on aarch64 Linux in a container, where the
        detection test now passes, and on macOS, where it is not built.

      14. 04658ed7
        Problem: Linux cache detection describes only CPU 0

        Flyology_Cachelines.Linux reads one L1 data-cache geometry: sysconf answers
        for the calling CPU, and the sysfs fallback reads cpu0. A host whose cores
        are not identical has more than one geometry, and neither mechanism says
        which core the reported one belongs to, or that others exist.

        macOS already publishes ordered performance levels, so the macOS body can
        prefer the highest-performing one. Linux publishes per-CPU descriptions and
        no single ordering, so the equivalent information has to be derived before
        any public per-core-type query can work on both platforms.

        Solution: Group CPUs into core classes and record what ordered them

        Detect_Core_Classes enumerates the CPUs the host lists as present, reads
        each one's L1 data-cache geometry and capacity, groups CPUs reporting
        identical values into a class, and counts each class.

        Classes are grouped on capacity and geometry together. Grouping on geometry
        alone merges two core types that happen to share an L1 data-cache size,
        which real designs do.

        Ordering uses whichever key separates the classes, and Core_Classes reports
        which one did, so a caller can tell an authoritative order from an inferred
        one:

        - Host_Reported: the kernel's per-CPU capacity values separated them.
        Capacity is the scheduler's own measure of relative CPU performance and
        accounts for microarchitecture and clock. Architectures selecting the
        generic topology code publish it under cpuN/cpu_capacity.
        - Inferred: no capacity separated them, so they are ordered by descending
        L1 data-cache capacity. That holds on current hybrid parts and carries
        no meaning on a host whose classes differ some other way. x86-64 does
        not publish capacity, so its hybrid parts land here.
        - Unordered: fewer than two classes, or nothing separated them.

        Cores and CPUs are counted separately. SMT siblings share one L1 data cache,
        so the cache's sharing list identifies which CPU represents a physical core.
        Counting logical CPUs as cores overstates a 24-core host with two threads
        per core by a factor of two.

        Detection fails closed. A missing or malformed CPU list leaves only CPU 0 to
        enumerate, enumeration is bounded, a CPU whose description cannot be read is
        skipped, and a host reporting more classes than the table holds reports none
        rather than a table that silently omits a class.

        Detect_Core_Classes takes the CPU root as a parameter defaulted to the real
        sysfs path. Grouping, ordering, and the SMT distinction cannot be reached on
        a uniform test host, so the detection test drives them with committed
        fixture trees: two classes separated only by capacity, two classes separated
        only by geometry with the smaller listed first, SMT pairs sharing one cache,
        and a CPU list with a gap.

        Nothing calls Detect_Core_Classes outside the test yet. The public
        per-core-type query, and the elaboration cost of walking every CPU, belong
        to the change that adds that query.

        Checks run: the crate suite on aarch64 Linux in a container and on macOS.
        Detection was also replayed against captured CPU descriptions from a 48-CPU
        x86-64 host with two threads per core, which reports 24 cores against 48
        CPUs and no capacity, and from an 80-CPU aarch64 host, which reports 80
        cores against 80 CPUs and a published capacity.

      15. ba8438da
        Problem: Cache queries cannot name a core class

        Flyology_Cachelines reports one L1 data-cache capacity. A host that combines
        core types has one per type, so a single value silently describes whichever
        type the platform body happened to pick and gives a caller no way to ask
        about the others, or to learn that others exist.

        The two platforms also disagreed. macOS reported the highest performance
        level, while Linux reported whichever cache its own mechanism described:
        sysconf for the calling CPU, sysfs for cpu0. The same call therefore meant
        different things on the two platforms.

        Solution: Make the core class an explicit parameter of every cache query

        Core_Class names one class of cores that report a single cache geometry.
        Core_Class_Count reports how many the host distinguishes, Core_Class_Cores
        and Core_Class_CPUs describe each one, and L1_Data_Cache_Size and
        L1_Data_Cache_Slots take the class they describe. The parameter defaults to
        Fastest_Core_Class, so existing calls keep compiling and now mean the same
        thing on both platforms: the class the host ranks highest.

        Core_Class_Ordering reports what produced that rank, because it is a host
        fact on some platforms and the crate's inference on others. macOS performance
        levels and the Linux per-CPU capacity values are Host_Reported. A host
        publishing no rank is Inferred, ordered by descending L1 data-cache capacity.
        Fewer than two classes is Unordered.

        Cores and CPUs are reported separately. Sibling CPUs under simultaneous
        multithreading share one core's L1 data cache, so a 24-core host with two
        threads per core reports 24 cores and 48 CPUs in one class.

        Hardware_Cache_Line_Size takes no class. macOS publishes no per-class line
        size, and the core types of current heterogeneous parts share one line size,
        so a per-class query would have one answer to give.

        The host is now inspected on first use rather than during elaboration.
        Describing every class means reading one description per CPU on Linux, which
        measures 14 ms for 48 CPUs and 24 ms for 80. A program that links this crate
        and never asks about the host should not pay that at startup. The inspection
        is idempotent, so a race on the first query can duplicate work but cannot
        produce a value neither caller computed; the ready flag is atomic and is set
        after the result is stored.

        Flyology_Cachelines.Platform now answers one Detect call describing the whole
        host, and the root package body owns the single memoization. The two Linux
        bodies share one translation and differ only in what they report when sysfs
        describes nothing: the x86-64 body can still read the calling CPU through
        CPUID. Flyology_Cachelines.Linux drops its own class and ordering types in
        favour of the public ones, so the crate has one Core_Class.

        The website cachelines guide is corrected alongside the API. Adding the Class
        parameter changed the generated GNATdoc anchors for L1_Data_Cache_Size and
        L1_Data_Cache_Slots, so the guide's links to them became dangling fragments;
        both now point at the regenerated anchors. The guide also claimed detection
        happens during package elaboration, which is no longer true. The new entities
        are linked to their generated entries on first mention.

        Checks run: the crate suite on macOS, where a 12P/4E host reports two
        host-ordered classes of 131072 and 65536 bytes across 12 and 4 cores; on
        aarch64 Linux in a container; and on an x86-64 Linux host with 24 cores and
        two threads per core, which exercises the CPUID body and reports 49152 bytes
        across 24 cores and 48 CPUs. GNATdoc builds with no warnings.

      16. 9782c81b
        Problem: The shared L2 cache is not reported

        Flyology_Cachelines reports L1 but not L2, so a caller sizing a working set
        against the level it will actually spill into has nothing to read.

        The flat sysctl this crate would naturally have used is wrong in the same way
        hw.l1dcachesize was, and by a larger factor. On a 12P/4E Apple silicon host
        hw.l2cachesize reports 4194304, the efficiency cluster's cache, against the
        performance cluster's 16777216. Adding L2 before core classes existed would
        have reproduced the original defect at four times the size instead of two.

        Reporting a capacity alone would also mislead. L2 is rarely private: that same
        host shares 16 MiB across six performance cores and 4 MiB across four
        efficiency cores, so neither figure is a per-core budget.

        Solution: Report L2 capacity and how many cores share it, per class

        L2_Cache_Size and L2_Sharing_Cores take the same core class as the L1
        queries. A sharing count of one means the cache is private to a core; a
        larger count means the reported capacity is divided among that many cores.
        The GNATdoc on each function points at the other, because reading either
        alone invites the per-core mistake.

        macOS reads hw.perflevelN.l2cachesize and hw.perflevelN.cpusperl2. Linux
        reads the level 2 entry of each CPU's cache description, counting the CPUs
        its shared_cpu_list names. Both counts arrive as logical CPUs and become core
        counts through the class's own threads-per-core ratio, so a host with two
        threads per core does not report twice the cores sharing a cache.

        Parsing a CPU list needs more than its leading index, so the Linux body gains
        List_Count, which sums the single indexes and inclusive ranges a list names.
        Describing L2 costs no extra file reads: the level 2 entry is found in the
        same pass over the cache indexes that already locates the level 1 data entry.

        The website cachelines guide gains the same pairing, with both names linked
        to their generated entries.

        Checks run: the crate suite on all three supported targets. A 12P/4E macOS
        host reports 16777216 bytes across 6 cores for its performance class and
        4194304 across 4 for its efficiency class, and the macOS test asserts that
        these come from the performance level rather than the flat name. An aarch64
        Linux host reports 16777216 across 6 cores. An x86-64 Linux host with 24
        cores and two threads per core reports 2097152 across 1 core, where sysfs
        gives 2048K shared by CPUs "0,24"; that run also compiles the CPUID body,
        which builds nowhere else. Fixtures cover a per-class shared L2, an L2 shared
        across SMT siblings, and a private L2. GNATdoc builds with no warnings.

    3. 9782c81b updated to 7be049fcindex 6e2db0ef

      1 source commit

      1. 7be049fc
        Problem: A stalled package mirror hangs CI instead of failing it

        The two OpenSSL install steps in the test job carried no bound, so a mirror
        that stops answering leaves apt waiting rather than returning an error. On
        2026-08-19 run 32297071503, job 96211136305 sat on "Install OpenSSL 3 on
        Linux" for 32 minutes and had to be cancelled by hand; it was the only check
        blocking PR #49. Its log shows apt-get update fetching noble-security
        InRelease at 20:13:04 and producing no further output until cancellation. The
        macOS half of the same job passed, so nothing was wrong with the tests.

        Left alone the job would have run to GitHub's six-hour default. Nothing else
        in either workflow was bounded either: the checkout, the Alire install, the
        index configuration, the Java and TLA+ downloads, and the GNATdoc install all
        reach the network under the same default, and no job in this repository
        declared a timeout at all, unlike the sibling repositories.

        Solution: Bound every job and every step that reaches the network

        Each job now declares a timeout-minutes, and so does each step that fetches
        something. The bounds are generous multiples of what healthy runs measure
        over the last 60 successful runs of each workflow, so they can only fire on a
        stall. Jobs: test observes at most 17 minutes on macOS and 11 on Linux and is
        bounded at 60; proof observes 6 minutes and TLA+ 7, both bounded at 30; the
        pages build observes 69 seconds and is bounded at 20, its deploy 10 seconds
        and bounded at 15. Steps: everything network-touching is bounded at 10
        minutes against observed maxima of 1 to 6 seconds, except the Alire install,
        which downloads the toolchain, observes 100 seconds, and is bounded at 15.

        A step timeout alone would only have converted the 32-minute hang into a
        10-minute one, because the stall is inside a single apt-get update that never
        returns. That command is now capped per attempt with timeout(1) and retried
        twice with 15 and 30 second backoff, so one unresponsive mirror costs a
        retry rather than the job. The install that follows is capped as well but not
        retried: a package that cannot be resolved should fail on the first try. The
        worst case is three 120-second attempts plus a 10-second kill grace, 45
        seconds of backoff, and a 190-second install, which is 10m25s and lands
        inside the 12-minute step bound, so the annotation naming the transient
        mirror is what the log ends on rather than a bare cancellation.

        GNU timeout is used directly rather than scripts/run-with-timeout.sh. That
        helper exists for portability to macOS, and this step is Linux-only.

        The TLA+ download gains --connect-timeout 30 and --max-time 120 alongside its
        existing --retry 3, because curl retries a failed transfer but not a stalled
        one, and --max-time resets per attempt. Four bounded attempts stay inside the
        step's 10 minutes.

        Build, test, proof, and model-checking steps keep no step bound. Their
        duration is workload-dependent, a bound sized for them would be a performance
        budget rather than a stall detector, and the job timeout already covers them.
        Nothing about what is installed, or how anything is built or tested, changes.

        Checks run: both workflows parse. The retry script was extracted from the
        committed YAML and driven under bash -e against stub apt-get invocations for
        five outcomes: first-try success runs one update and one install; two
        failures then success runs three updates and installs; three failures exit 1
        with the annotation and never install; an install failure propagates its exit
        status without retrying; and exit 124, which is what timeout(1) reports when
        it kills a stalled command, is treated as retryable. The real commands were
        then run in an ubuntu:24.04 container on coreutils 9.4, the runner's version:
        the bounded update succeeds, interrupting one mid-flight reports 124, a
        retry after that kill still succeeds rather than inheriting a poisoned apt
        state, and the bounded install still yields OpenSSL 3.0.13 through pkg-config.

        The convention is recorded in AGENTS.md so it holds for new steps, and it
        matches the job-level timeouts already used in flyology-http and
        gnat-patches, whose install steps want the same treatment.

        Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

    4. 7be049fc updated to a53da35dindex b5569962

      1 source commit

      1. a53da35d
        Problem: The allocators dependency accepts any version

        The allocator crate is developed alongside the runtime in this repository and
        released on the same development line, but the dependency on it is declared as
        "*". Nothing stops a dependent from resolving an allocator release built for a
        different line, and the index has been carrying a tighter constraint by hand to
        compensate.

        Solution: Constrain allocators to its development line

        Declare the line the allocator crate actually publishes, so the constraint
        travels with the manifest instead of being reapplied wherever it is indexed.

        Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

    Compare source revisions
    Development update

    flyology_postgres 0.1.1-dev

    2 updates: 92212697 through f9101bc4

    Postgres client and protocol server for Flyology tasks

    Manifest fields
    origin
    Show all 2 updates
    1. 92212697 updated to a8af8e1findex 510cfcf6

      1 source commit

      1. a8af8e1f
        Problem: SQL differential testing covers only a small hand-written sample

        The native PostgreSQL parser and generated owned AST support five grammar versions, but CI does not exercise the upstream regression corpus. Parser generator, scanner, semantic-action, and conversion defects can therefore survive the existing focused cases.

        Solution: compare every PostgreSQL regression file against pinned oracles

        Acquire and checksum the exact upstream corpora, recover oracle-valid statements from psql-oriented and expected-error files, compare native and owned AST layers, cache the inputs in CI, and correct the generator/runtime defects exposed across PostgreSQL 14 through 18.

    2. a8af8e1f updated to f9101bc4index 6c4de3f9

      2 source commits

      1. f3300652
        Problem: The workbench pins contradict the versions it requires

        The workbench pinned Flyology and Flyology HTTP to commits predating the 0.1.1
        development line while requiring that line, so the pins named sources declaring
        0.1.0-dev and had fallen 72 and 41 commits behind their branches. Both crates
        are now published to the index for the required line, leaving the pins with
        nothing to contribute but the contradiction.

        Solution: Resolve both dependencies from the index

        Drop the commit pins so the required development line selects the sources, and
        the workbench tracks them the way every other dependent does.

        Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

      2. f9101bc4
        Problem: SQL pins hide which versions dependents need

        Each SQL crate pins its siblings by path for local development and leaves the
        matching dependencies declared as "*", because the pin supplies the version.
        Local builds resolve through the pins and never notice. A path cannot cross
        into the index, so anything depending on these crates from outside the
        repository is free to resolve any version at all.

        Solution: Declare the versions the pins stand in for

        Constrain each pinned dependency to the development line its pinned checkout
        provides, so the same versions are selected once the pins are gone. Local
        resolution is unchanged, since a pin still takes precedence.

        Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

    Compare source revisions
    Development update

    flyology_postgres_sql 0.1.1-dev

    2 updates: 92212697 through f9101bc4

    Versioned PostgreSQL raw SQL parser and Ada syntax tree

    Manifest fields
    description, origin
    Show all 2 updates
    1. 92212697 updated to a8af8e1findex 510cfcf6

      1 source commit

      1. a8af8e1f
        Problem: SQL differential testing covers only a small hand-written sample

        The native PostgreSQL parser and generated owned AST support five grammar versions, but CI does not exercise the upstream regression corpus. Parser generator, scanner, semantic-action, and conversion defects can therefore survive the existing focused cases.

        Solution: compare every PostgreSQL regression file against pinned oracles

        Acquire and checksum the exact upstream corpora, recover oracle-valid statements from psql-oriented and expected-error files, compare native and owned AST layers, cache the inputs in CI, and correct the generator/runtime defects exposed across PostgreSQL 14 through 18.

    2. a8af8e1f updated to f9101bc4index 6c4de3f9

      2 source commits

      1. f3300652
        Problem: The workbench pins contradict the versions it requires

        The workbench pinned Flyology and Flyology HTTP to commits predating the 0.1.1
        development line while requiring that line, so the pins named sources declaring
        0.1.0-dev and had fallen 72 and 41 commits behind their branches. Both crates
        are now published to the index for the required line, leaving the pins with
        nothing to contribute but the contradiction.

        Solution: Resolve both dependencies from the index

        Drop the commit pins so the required development line selects the sources, and
        the workbench tracks them the way every other dependent does.

        Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

      2. f9101bc4
        Problem: SQL pins hide which versions dependents need

        Each SQL crate pins its siblings by path for local development and leaves the
        matching dependencies declared as "*", because the pin supplies the version.
        Local builds resolve through the pins and never notice. A path cannot cross
        into the index, so anything depending on these crates from outside the
        repository is free to resolve any version at all.

        Solution: Declare the versions the pins stand in for

        Constrain each pinned dependency to the development line its pinned checkout
        provides, so the same versions are selected once the pins are gone. Local
        resolution is unchanged, since a pin still takes precedence.

        Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

    Compare source revisions
    Development update

    flyology_postgres_sql_core 0.1.1-dev

    2 updates: 92212697 through f9101bc4

    Shared native runtime for versioned Flyology PostgreSQL parsers

    Manifest fields
    origin
    Show all 2 updates
    1. 92212697 updated to a8af8e1findex 510cfcf6

      1 source commit

      1. a8af8e1f
        Problem: SQL differential testing covers only a small hand-written sample

        The native PostgreSQL parser and generated owned AST support five grammar versions, but CI does not exercise the upstream regression corpus. Parser generator, scanner, semantic-action, and conversion defects can therefore survive the existing focused cases.

        Solution: compare every PostgreSQL regression file against pinned oracles

        Acquire and checksum the exact upstream corpora, recover oracle-valid statements from psql-oriented and expected-error files, compare native and owned AST layers, cache the inputs in CI, and correct the generator/runtime defects exposed across PostgreSQL 14 through 18.

    2. a8af8e1f updated to f9101bc4index 6c4de3f9

      2 source commits

      1. f3300652
        Problem: The workbench pins contradict the versions it requires

        The workbench pinned Flyology and Flyology HTTP to commits predating the 0.1.1
        development line while requiring that line, so the pins named sources declaring
        0.1.0-dev and had fallen 72 and 41 commits behind their branches. Both crates
        are now published to the index for the required line, leaving the pins with
        nothing to contribute but the contradiction.

        Solution: Resolve both dependencies from the index

        Drop the commit pins so the required development line selects the sources, and
        the workbench tracks them the way every other dependent does.

        Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

      2. f9101bc4
        Problem: SQL pins hide which versions dependents need

        Each SQL crate pins its siblings by path for local development and leaves the
        matching dependencies declared as "*", because the pin supplies the version.
        Local builds resolve through the pins and never notice. A path cannot cross
        into the index, so anything depending on these crates from outside the
        repository is free to resolve any version at all.

        Solution: Declare the versions the pins stand in for

        Constrain each pinned dependency to the development line its pinned checkout
        provides, so the same versions are selected once the pins are gone. Local
        resolution is unchanged, since a pin still takes precedence.

        Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

    Compare source revisions
    Development update

    flyology_postgres_sql_v14 0.1.1-dev

    2 updates: 92212697 through f9101bc4

    Native PostgreSQL 14 parser and owned Ada AST

    Manifest fields
    origin
    Show all 2 updates
    1. 92212697 updated to a8af8e1findex 510cfcf6

      1 source commit

      1. a8af8e1f
        Problem: SQL differential testing covers only a small hand-written sample

        The native PostgreSQL parser and generated owned AST support five grammar versions, but CI does not exercise the upstream regression corpus. Parser generator, scanner, semantic-action, and conversion defects can therefore survive the existing focused cases.

        Solution: compare every PostgreSQL regression file against pinned oracles

        Acquire and checksum the exact upstream corpora, recover oracle-valid statements from psql-oriented and expected-error files, compare native and owned AST layers, cache the inputs in CI, and correct the generator/runtime defects exposed across PostgreSQL 14 through 18.

    2. a8af8e1f updated to f9101bc4index 6c4de3f9

      2 source commits

      1. f3300652
        Problem: The workbench pins contradict the versions it requires

        The workbench pinned Flyology and Flyology HTTP to commits predating the 0.1.1
        development line while requiring that line, so the pins named sources declaring
        0.1.0-dev and had fallen 72 and 41 commits behind their branches. Both crates
        are now published to the index for the required line, leaving the pins with
        nothing to contribute but the contradiction.

        Solution: Resolve both dependencies from the index

        Drop the commit pins so the required development line selects the sources, and
        the workbench tracks them the way every other dependent does.

        Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

      2. f9101bc4
        Problem: SQL pins hide which versions dependents need

        Each SQL crate pins its siblings by path for local development and leaves the
        matching dependencies declared as "*", because the pin supplies the version.
        Local builds resolve through the pins and never notice. A path cannot cross
        into the index, so anything depending on these crates from outside the
        repository is free to resolve any version at all.

        Solution: Declare the versions the pins stand in for

        Constrain each pinned dependency to the development line its pinned checkout
        provides, so the same versions are selected once the pins are gone. Local
        resolution is unchanged, since a pin still takes precedence.

        Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

    Compare source revisions
    Development update

    flyology_postgres_sql_v15 0.1.1-dev

    2 updates: 92212697 through f9101bc4

    Native PostgreSQL 15 parser and owned Ada AST

    Manifest fields
    origin
    Show all 2 updates
    1. 92212697 updated to a8af8e1findex 510cfcf6

      1 source commit

      1. a8af8e1f
        Problem: SQL differential testing covers only a small hand-written sample

        The native PostgreSQL parser and generated owned AST support five grammar versions, but CI does not exercise the upstream regression corpus. Parser generator, scanner, semantic-action, and conversion defects can therefore survive the existing focused cases.

        Solution: compare every PostgreSQL regression file against pinned oracles

        Acquire and checksum the exact upstream corpora, recover oracle-valid statements from psql-oriented and expected-error files, compare native and owned AST layers, cache the inputs in CI, and correct the generator/runtime defects exposed across PostgreSQL 14 through 18.

    2. a8af8e1f updated to f9101bc4index 6c4de3f9

      2 source commits

      1. f3300652
        Problem: The workbench pins contradict the versions it requires

        The workbench pinned Flyology and Flyology HTTP to commits predating the 0.1.1
        development line while requiring that line, so the pins named sources declaring
        0.1.0-dev and had fallen 72 and 41 commits behind their branches. Both crates
        are now published to the index for the required line, leaving the pins with
        nothing to contribute but the contradiction.

        Solution: Resolve both dependencies from the index

        Drop the commit pins so the required development line selects the sources, and
        the workbench tracks them the way every other dependent does.

        Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

      2. f9101bc4
        Problem: SQL pins hide which versions dependents need

        Each SQL crate pins its siblings by path for local development and leaves the
        matching dependencies declared as "*", because the pin supplies the version.
        Local builds resolve through the pins and never notice. A path cannot cross
        into the index, so anything depending on these crates from outside the
        repository is free to resolve any version at all.

        Solution: Declare the versions the pins stand in for

        Constrain each pinned dependency to the development line its pinned checkout
        provides, so the same versions are selected once the pins are gone. Local
        resolution is unchanged, since a pin still takes precedence.

        Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

    Compare source revisions
    Development update

    flyology_postgres_sql_v16 0.1.1-dev

    2 updates: 92212697 through f9101bc4

    Native PostgreSQL 16 parser and owned Ada AST

    Manifest fields
    origin
    Show all 2 updates
    1. 92212697 updated to a8af8e1findex 510cfcf6

      1 source commit

      1. a8af8e1f
        Problem: SQL differential testing covers only a small hand-written sample

        The native PostgreSQL parser and generated owned AST support five grammar versions, but CI does not exercise the upstream regression corpus. Parser generator, scanner, semantic-action, and conversion defects can therefore survive the existing focused cases.

        Solution: compare every PostgreSQL regression file against pinned oracles

        Acquire and checksum the exact upstream corpora, recover oracle-valid statements from psql-oriented and expected-error files, compare native and owned AST layers, cache the inputs in CI, and correct the generator/runtime defects exposed across PostgreSQL 14 through 18.

    2. a8af8e1f updated to f9101bc4index 6c4de3f9

      2 source commits

      1. f3300652
        Problem: The workbench pins contradict the versions it requires

        The workbench pinned Flyology and Flyology HTTP to commits predating the 0.1.1
        development line while requiring that line, so the pins named sources declaring
        0.1.0-dev and had fallen 72 and 41 commits behind their branches. Both crates
        are now published to the index for the required line, leaving the pins with
        nothing to contribute but the contradiction.

        Solution: Resolve both dependencies from the index

        Drop the commit pins so the required development line selects the sources, and
        the workbench tracks them the way every other dependent does.

        Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

      2. f9101bc4
        Problem: SQL pins hide which versions dependents need

        Each SQL crate pins its siblings by path for local development and leaves the
        matching dependencies declared as "*", because the pin supplies the version.
        Local builds resolve through the pins and never notice. A path cannot cross
        into the index, so anything depending on these crates from outside the
        repository is free to resolve any version at all.

        Solution: Declare the versions the pins stand in for

        Constrain each pinned dependency to the development line its pinned checkout
        provides, so the same versions are selected once the pins are gone. Local
        resolution is unchanged, since a pin still takes precedence.

        Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

    Compare source revisions
    Development update

    flyology_postgres_sql_v17 0.1.1-dev

    2 updates: 92212697 through f9101bc4

    Native PostgreSQL 17 parser and owned Ada AST

    Manifest fields
    origin
    Show all 2 updates
    1. 92212697 updated to a8af8e1findex 510cfcf6

      1 source commit

      1. a8af8e1f
        Problem: SQL differential testing covers only a small hand-written sample

        The native PostgreSQL parser and generated owned AST support five grammar versions, but CI does not exercise the upstream regression corpus. Parser generator, scanner, semantic-action, and conversion defects can therefore survive the existing focused cases.

        Solution: compare every PostgreSQL regression file against pinned oracles

        Acquire and checksum the exact upstream corpora, recover oracle-valid statements from psql-oriented and expected-error files, compare native and owned AST layers, cache the inputs in CI, and correct the generator/runtime defects exposed across PostgreSQL 14 through 18.

    2. a8af8e1f updated to f9101bc4index 6c4de3f9

      2 source commits

      1. f3300652
        Problem: The workbench pins contradict the versions it requires

        The workbench pinned Flyology and Flyology HTTP to commits predating the 0.1.1
        development line while requiring that line, so the pins named sources declaring
        0.1.0-dev and had fallen 72 and 41 commits behind their branches. Both crates
        are now published to the index for the required line, leaving the pins with
        nothing to contribute but the contradiction.

        Solution: Resolve both dependencies from the index

        Drop the commit pins so the required development line selects the sources, and
        the workbench tracks them the way every other dependent does.

        Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

      2. f9101bc4
        Problem: SQL pins hide which versions dependents need

        Each SQL crate pins its siblings by path for local development and leaves the
        matching dependencies declared as "*", because the pin supplies the version.
        Local builds resolve through the pins and never notice. A path cannot cross
        into the index, so anything depending on these crates from outside the
        repository is free to resolve any version at all.

        Solution: Declare the versions the pins stand in for

        Constrain each pinned dependency to the development line its pinned checkout
        provides, so the same versions are selected once the pins are gone. Local
        resolution is unchanged, since a pin still takes precedence.

        Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

    Compare source revisions
    Development update

    flyology_postgres_sql_v18 0.1.1-dev

    2 updates: 92212697 through f9101bc4

    Native PostgreSQL 18 parser and owned Ada AST

    Manifest fields
    origin
    Show all 2 updates
    1. 92212697 updated to a8af8e1findex 510cfcf6

      1 source commit

      1. a8af8e1f
        Problem: SQL differential testing covers only a small hand-written sample

        The native PostgreSQL parser and generated owned AST support five grammar versions, but CI does not exercise the upstream regression corpus. Parser generator, scanner, semantic-action, and conversion defects can therefore survive the existing focused cases.

        Solution: compare every PostgreSQL regression file against pinned oracles

        Acquire and checksum the exact upstream corpora, recover oracle-valid statements from psql-oriented and expected-error files, compare native and owned AST layers, cache the inputs in CI, and correct the generator/runtime defects exposed across PostgreSQL 14 through 18.

    2. a8af8e1f updated to f9101bc4index 6c4de3f9

      2 source commits

      1. f3300652
        Problem: The workbench pins contradict the versions it requires

        The workbench pinned Flyology and Flyology HTTP to commits predating the 0.1.1
        development line while requiring that line, so the pins named sources declaring
        0.1.0-dev and had fallen 72 and 41 commits behind their branches. Both crates
        are now published to the index for the required line, leaving the pins with
        nothing to contribute but the contradiction.

        Solution: Resolve both dependencies from the index

        Drop the commit pins so the required development line selects the sources, and
        the workbench tracks them the way every other dependent does.

        Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

      2. f9101bc4
        Problem: SQL pins hide which versions dependents need

        Each SQL crate pins its siblings by path for local development and leaves the
        matching dependencies declared as "*", because the pin supplies the version.
        Local builds resolve through the pins and never notice. A path cannot cross
        into the index, so anything depending on these crates from outside the
        repository is free to resolve any version at all.

        Solution: Declare the versions the pins stand in for

        Constrain each pinned dependency to the development line its pinned checkout
        provides, so the same versions are selected once the pins are gone. Local
        resolution is unchanged, since a pin still takes precedence.

        Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

    Compare source revisions
    Development update

    flyology_quic 0.1.1-dev

    3 updates: ddbba90d through dac7fa90

    Ada-native QUIC transport for Flyology tasks

    Manifest fields
    origin
    Show all 3 updates
    1. ddbba90d updated to d99490cfindex 510cfcf6

      3 source commits

      1. 1802f1c9
        Problem: Proof and WebSocket qualification depend on manual runs

        SPARK proof regressions and Autobahn conformance failures can go unnoticed because CI does not execute those campaigns. The existing nightly schedule covers other qualifications but not these policy and protocol checks.

        Solution: Gate proofs and schedule Autobahn qualification

        Run the complete QUIC and HTTP proof suite for every CI trigger and add a scheduled matrix for all maintained Autobahn profiles and task lanes, including matched OpenSSL provenance for secure profiles.

      2. 3d0df29f
        Problem: Hosted level-one proofs time out nondeterministically

        The pull request proof job twice exhausts its level-one prover budget on QUIC ACK range obligations, even though the same obligations pass locally. This leaves an otherwise healthy CI run red and makes proof coverage unreliable on hosted runners.

        Solution: Give CI level-two proof effort

        Let both proof scripts accept FLYOLOGY_PROOF_LEVEL while preserving level one as the default for manual runs. Set the CI proof job to level two so hosted provers have enough effort to complete the full QUIC and HTTP campaigns.

      3. d99490cf
        Problem: HTTP benchmark cannot prepare Flyology runtime from worktrees

        The benchmark runner assumes Flyology runtime scripts live in the HTTP project root. Separate Codex worktrees and Alire dependency layouts do not provide that path, so runtime preparation fails before the benchmark can build.

        Solution: Prepare the runtime from the resolved Flyology root

        Resolve Flyology through the shared dependency-root helper and use that root when invoking prepare-rts.sh, preserving explicit, adjacent monorepo, and Alire-provided dependency layouts.

    2. d99490cf updated to 439a9fb6index 6e2db0ef

      30 source commits

      1. 24c1ea29
        Problem: Running routers cannot be reconfigured atomically

        Servers must currently mutate route setup state directly and cannot safely publish coordinated handler, policy, and middleware changes while requests are in flight. Callers also lack stable identities for addressing registered routes and middleware.

        Solution: Publish immutable router generations through stable identities

        Add opaque route and middleware IDs, transactional update operations, stale-writer detection, and single-load atomic generation publication. Exercise replacement and concurrent dispatch behavior, document the runtime and memory tradeoffs, and add the workflow to the server guide.

      2. 5e5aae59
        Problem: Router publication adds a generation indirection

        Every dispatch loads the published generation and then follows a second pointer to reach its immutable configuration. Each successful update also allocates a separate generation holder solely for retention bookkeeping.

        Solution: Publish configuration allocations directly

        Link retained configurations through their own private history field and atomically publish the configuration address. This removes the holder allocation and one dependent request-path load without changing stale-update or lifetime behavior.

      3. 1df8c3a6
        Problem: Retained router generations are linked by raw address

        The retention chain, the publication gate, and the update base all carry
        System.Address, so recovering a configuration needs an unchecked conversion
        from an address-conversion pointer into a pool-specific access type. Router
        initialization also allocates its first configuration in the declarative
        part, where the handler written to release a failed allocation cannot see
        it: an exception raised there propagates without reaching the handler.

        Solution: Link retained configurations through a typed access

        Complete the configuration type from an incomplete declaration and make its
        access type general, so Previous, First_Configuration, the update base, and
        the publication gate all hold access values and the unchecked conversion
        disappears. The address round trip now stays on the published atomic word
        alone. Allocate the first configuration in the statement part so its handler
        covers the allocation it was written for.

      4. 38b98060
        Problem: Direct registration can tear a generation being served

        Add, Add_Middleware, Add_Route_Middleware, Mount, and the two direct setters
        write the currently published configuration in place, and they admit the new
        element before they write it: the count is incremented first. A request that
        races such a registration reads the raised count and then a route with a null
        handler or a middleware entry with a null component, so the pipeline raises
        Constraint_Error. Only the two setters carried a setup-only note, and the
        identity-returning registration overloads carried none.

        Solution: Seal the router at its first dispatch

        Publish a seal word from the first dispatch and refuse every direct
        registration and setter afterwards with Route_Error naming the update path.
        The dispatch cost is one acquire load of a clean shared line, since the store
        happens only while the word is still clear. Fill each route and middleware
        slot before the count admits it so the ordering is sound on its own, and
        state the sealing rule on the router type and the affected operations.

      5. 1fd5ed9b
        Problem: Mounting makes a middleware registration unaddressable

        Mount assigns a fresh identity to every middleware entry it copies into the
        mounted routes, so the identity the application holds for a subrouter's
        component matches nothing in the destination. Remove_Middleware and
        Replace_Middleware then raise while the mounted copies keep running the old
        component, even though both already walk every route chain accumulating
        matches, which only makes sense when one identity can appear in several
        chains. Begin_Update also accepted a mounted generation, and two candidate
        setters skipped the mounted guard the other mutators apply.

        Solution: Carry the source registration identity through a mount

        Copy mounted middleware entries verbatim so one identity names every chain
        that carries the registration. Refuse Begin_Update on a mounted generation,
        which covers every candidate mutator in one place, and add the guard to the
        admission and challenge setters that lacked it. State the mounting rule on
        the identity type, on Remove_Middleware, and in the server guide.

      6. 8244e2fb
        Problem: A stale candidate cannot be rebuilt in the same update

        Commit raises Stale_Update while the candidate is still attached, so
        Begin_Update on that object then raises Program_Error. The documented retry
        loop only works because it declares the update inside the loop; hoisting it,
        which is the obvious way to avoid re-entering the declaration, deadlocks the
        caller into an unusable object. There is also no way to give up on a
        candidate that failed validation.

        The concurrency audit could not fail cleanly either. Its workers park on a
        barrier that a failure before Start never opens, and the join waits for all
        four to finish with no bound, so a setup error hangs the audit until the
        harness timeout instead of reporting. Its assertion also could not tell a
        run that spanned a publication from one that never observed a change.

        Solution: Release a stale candidate and bound the audit

        Release the candidate when Commit rejects it as stale, since its base is gone
        and it can never be published, and leave a validation failure active so the
        caller can correct and commit it. Add Abandon for an explicit discard.

        Rebuild the audit around a cancellable barrier, bounded joins, and a fixed
        publication count chosen odd so the closing request of every worker has one
        correct answer. Workers now record a pre-publication and a post-publication
        observation, so the test proves it spanned a generation change. Cover the
        duplicate-name and ambiguity rejections that candidate Add defers to Commit,
        and the Set_Match, Rename, Set_Middleware_Stage, and admission operations
        that had no coverage at all.

      7. 5e9b0b41
        Problem: Introspection loops can straddle a router commit

        Every introspection operation takes its own acquire load, so a caller that
        reads Route_Count and then describes each index reads two generations. A
        commit that removes a route between the two calls makes the last index
        invalid and Describe_Route raises Constraint_Error. The same split affects
        Route_Middleware_Count with Describe_Route_Middleware. A diagnostics endpoint
        enumerating routes therefore fails intermittently on exactly the deployments
        runtime reconfiguration is for, and nothing lets a caller pin a generation.

        Solution: Add a snapshot that pins one generation

        Add a Snapshot that captures the published generation, with the whole
        introspection surface available on it. Route the Router forms and the
        Snapshot forms through shared configuration-level operations so both answer
        identically. Retained generations already outlive any snapshot, so the
        snapshot only holds a reference; its finalization is the hook a later
        reclamation scheme needs.

      8. b345dc6f
        Problem: Retained router generations are neither visible nor releasable

        Commit links every superseded configuration into the router's retention
        chain, and only router finalization frees it. Retention is what keeps an
        in-flight dispatch from reading freed storage, but nothing bounds it and
        nothing reports it: a control plane that commits periodically grows the
        chain for the whole process lifetime with no way to observe the growth and
        no way to release it short of destroying the router.

        Solution: Report retained generations and release them on demand

        Add Retained_Generations so the growth is measurable, and Reclaim to release
        every superseded generation while keeping the published one. Reclaim states
        its precondition plainly: the caller must know that no dispatch is running
        and no snapshot of a superseded generation is live, and that is not checked.
        This keeps the request path free of reader accounting while giving a drained
        server a way to return the memory.

      9. e0a9e1b8
        Problem: Ambiguity checks re-split patterns they already compiled

        Registration compiles each pattern into a Segment_List so dispatch does not
        split it per request, but the ambiguity checks throw that away. Patterns
        Overlap and Specificity both take a String and split it again, so Check_Add
        re-splits every stored pattern on every registration and Commit re-splits
        both sides of every route pair. Add also computed the same split twice, once
        for storage and once for the score. The name-keyed Add_Route_Middleware
        scanned for the name, took an identity, then re-read the router and scanned
        again for that identity, which can report an identity failure for a name
        that does resolve. Name comparisons allocated a String per route inspected.

        Solution: Compare the segments and score each route already carries

        Take a Segment_List in Patterns_Overlap and Specificity, so both the
        registration check and the commit check read the stored segments and the
        stored score. Order the cheap score comparison before the segment walk.
        Compile each pattern once per Add. Resolve the name-keyed middleware
        overload in one pass over one generation. Compare names against the stored
        Unbounded_String instead of converting each one.

        Cover the result with an oracle: for each of eight pattern pairs, assert the
        registration decision and the commit decision are both the expected verdict.

      10. bdcfbc8c
        Problem: The server guide predates the update lifecycle it describes

        The guide still tells applications to bound their update rate when retained
        memory matters, which describes a rate tradeoff rather than growth the
        router now reports and can release. It states that direct registration must
        not run concurrently with dispatch without saying the router enforces that.
        It describes per-call introspection as a snapshot, which is what the new
        Snapshot type actually provides, and it tells a caller to rebuild a stale
        candidate without saying the candidate is already released.

        Solution: Describe sealing, snapshots, and generation retention

        Replace the retention paragraph with Retained_Generations and Reclaim, and
        state Reclaim's unchecked precondition beside the call. Say that the first
        dispatch seals the router and what a later direct registration raises. Add a
        short section for traversing one generation with Take_Snapshot, and record
        that Stale_Update releases its candidate while a validation failure keeps
        one for correction. Every new API mention links its generated GNATdoc entry,
        and all 286 generated-API links on the hand-written pages resolve.

      11. 799995fd
        Problem: A generation can be copied into a dispatch parameter

        Router_Configuration is a large non-limited discriminated record, so RM 6.2
        leaves by-copy or by-reference to the implementation for an in parameter.
        Dispatch_Configuration takes a generation that way, and so does every
        introspection and validation operation that reads one. GNAT passes them by
        reference and the request-path measurements show no copy, but nothing in the
        language requires it. An implementation that chose by-copy would duplicate a
        whole generation, with every route pattern, segment list, and middleware
        name, on each request.

        Solution: Take every generation parameter explicitly aliased

        An explicitly aliased parameter is passed by reference by definition, so
        mark all fourteen Router_Configuration parameters aliased. Every actual is
        already an aliased view reached through a Configuration_Access, so no call
        site changes. The guarantee is now a property of the declaration rather than
        of one compiler's choice.

      12. 977add4a
        Problem: No benchmark isolates dispatch against router reloads

        The published-generation word a dispatch reads and the word a commit writes
        live in the same router object, so a reload can invalidate the line the
        dispatchers are reading. Nothing measures that. The existing benchmark
        servers run over sockets and an external load generator, where connection
        and syscall cost hides an effect this small, and none of them reload the
        router while traffic runs.

        Solution: Add an in-process router reload benchmark

        Drive routed dispatch from worker tasks over an allocation-free in-memory
        transport, with one loader task republishing the configuration at a chosen
        rate, and sweep that rate against otherwise identical traffic. Each worker
        counts on its own stack and reports once at the end, so the harness adds no
        contention of its own to the thing being measured.

        The runner repeats each rate as independent process runs and reports best,
        median, worst, and spread, because code layout changes per link and process
        placement dominates repetition inside one run. Reporting the spread is the
        point: an effect smaller than it cannot be claimed from this harness.

      13. 926fed4b
        Problem: The router's dispatch-read words share a region with writer state

        Every dispatch reads the published-generation word and the seal word. Both
        sit in the same record as First_Configuration and the publication gate,
        which only a commit touches, and nothing in the declaration separates the
        two groups. Whatever layout the compiler happens to produce today is a
        consequence of field order and padding, not a property anyone stated.

        Solution: Place the two dispatch-read words in one interference region

        Group them with Flyology_Cachelines.Padded_Groups, so a dispatch fetches one
        region rather than two and a commit dirties the readers' region rather than
        whatever else landed beside it. The two words have the compatible ownership
        that a group requires: each is read by every dispatch and written only by a
        commit.

        This is not a measured improvement and must not be read as one. A commit
        dirties the readers' region once, not once per dispatch, so the cost follows
        the reload rate rather than the traffic: between 10 and 100 reloads per
        second it is 0.0004% to 0.004% of throughput, four orders of magnitude below
        what the reload benchmark can separate from run-to-run spread. The change is
        made because the layout is then correct by declaration instead of by
        accident. The benchmark now records what it can and cannot resolve, so the
        question is not reopened on the assumption that a measurement is available.

      14. 8cae2c89
        Problem: A stalled package mirror burns a runner instead of failing

        The HTTP/2 qualification job installs its independent peer with a bare
        sudo apt-get update, and no step in either workflow bounds its own runtime.
        When the mirror stops answering, apt-get does not fail; it waits. The step
        waits with it, and the only thing that eventually ends the run is the job
        timeout, or a person noticing.

        On 2026-08-19 that happened three times. Run 32226557711 on main sat on the
        update for the whole 150-minute job budget before the job timeout ended it,
        with nobody watching. Runs 32278682887 and 32294697524 sat there 83 and 64
        minutes before someone cancelled them by hand. The same job finishes in 8 to
        14 minutes when the mirror answers, and the install itself takes 11 seconds
        at the median, so each of those runs spent between four and eleven times the
        job's whole healthy duration waiting on one command. A run that hangs also
        reads as a run that is working: there is no failure to retry, and the
        concurrency group keeps the branch occupied until someone intervenes.

        Solution: Bound every network step, and retry the update that stalls

        Give each step that reaches the network a timeout-minutes bound, sized
        against the slowest healthy observation over the preceding 60 runs rather
        than against a guess, so a step that trips one has stalled rather than run
        slowly. Checking out sources and configuring the index finish in seconds and
        are given 5 minutes; the peer install runs 11 seconds at the median and 5
        minutes at its slowest and is given 15. Installing Alire is given 15 on
        different grounds: every observation of it is a cache hit, so the
        observations bound the cached path and say nothing about a cold toolchain
        download.

        Wrap apt-get update in three attempts, each bounded on its own by timeout,
        because the step bound alone would convert a stall into a failure but not
        into a recovery. A wedged mirror connection now becomes a retry against a
        fresh one, so a single transient failure does not fail the job, and the step
        bound stays a backstop rather than the mechanism that catches the common
        case. Only the update is retried: it is the command that stalled, and it is
        the one here that is safe to interrupt and repeat, since a killed run leaves
        partial package lists that the next run refetches. Retrying apt-get install
        would risk resuming from a half-configured dpkg state to no purpose.

        The same failure mode existed in two other places and is closed the same
        way. The Pages workflow had no job-level timeout at all, so a stall there ran
        to the six-hour GitHub default; both its jobs now carry one, and its fetch
        and install steps carry step bounds. The h3spec download in the HTTP/3
        conformance script used a bare curl -fL, which hangs on a stalled connection
        exactly as apt-get did; it now retries with a per-attempt time limit, which
        the existing checksum makes safe, because a truncated or resumed body never
        survives it.

        Nothing about what is installed or how anything is built or tested changes.
        On a healthy run every bound is untouched and every command runs as before;
        the bounds only decide how a stalled run ends.

        Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

      15. 27a8ee59
        Problem: the component getters and Resolve are unmeasured

        flyology_iri_benchmark times can_parse and parse_href over the pinned URL corpus. Neither reaches a component getter: can_parse constructs nothing, and parse_href consumes only the stored serialization length. The paths that read components back out of an already parsed reference, and Resolve above them, have no benchmark at all, so a change to them can be argued only from reading the code.

        Solution: Add a flyology_bench harness for those paths

        flyology_iri_resolve_benchmark reads all eight components at three reference lengths and resolves the RFC 3986 section 5.4 references against a short and a long base. It carries its own inputs, so unlike benchmark.sh it needs neither the Ada URL checkout nor the pinned corpus. Batches fold a value derived from each result into an accumulator handed to a barrier after the ending timestamp, and each iteration advances to a different input.

        Two builds of one library cannot share a process, so before/after runs join through Flyology_Bench.Baselines, whose fingerprint refuses a comparison across operating system, architecture, compiler, or build mode while deliberately excluding the library revision. scripts/resolve-benchmark.sh selects the release mode the published medians measure and passes it to the binary for that fingerprint. Diagnose and Parse do coexist, so the validation pair is a real paired Compare.

        Requested axes are Process_Resource_Metrics, the portable Darwin/Linux set; the metrics CSV reports each axis's collection status rather than leaving it assumed.

      16. d45630c0
        Problem: Slice copies the whole reference for one component

        Every public component getter reaches the stored serialization through the private Slice helper, which materialized the entire reference with To_String and then returned one range of it. The release objects show that call sited unconditionally and ahead of the zero-span test, so an absent component paid a whole-reference copy and a present one paid two allocations and two copies. Reading a four-character scheme out of a 233-byte IRI copied 233 bytes and then four. Resolve sits directly on top of that and reads Path four times and the base path twice. Remove_Dot_Segments, which runs on essentially every resolution, renormalized its input to one-based indexing through an Unbounded round trip.

        Solution: Copy only the component, and read each path once

        Slice now calls Ada.Strings.Unbounded.Slice, keeping the zero guard ahead of it because an absent component has First = 0 and that subprogram takes a Positive Low. The getters compile to a tail call to that subprogram on the present path and to an eight-byte bounds allocation on the absent one. The returned bounds do not change: GNAT's Slice returns the underlying Low .. High range, which is what the discarded whole-text copy was sliced by. Remove_Dot_Segments renormalizes with a constrained subtype instead of the heap. Resolve hoists the relative path and the base path into locals.

        Release-mode medians on an Apple M3 Max, interleaved before/after/before/after against an unrelated build holding the load average near 25, with the repeated pre-change round as a drift control: reading all eight components falls 41.9% at 44 bytes, 33.5% at 235, and 63.8% at 2,009; resolution falls 22.2% against an 18-byte base and 15.5% against a 233-byte one. The drift control landed within 3% of its own first round. Process_RSS_Change and both page-fault axes read zero on both sides, as expected for churn the allocator reuses within a batch; wall time and thread CPU time are the axes that respond.

        Component tests now name the absent components, since the zero guard is what keeps an absent span away from a Positive parameter.

      17. 4df3c149
        Problem: Resolve builds a Reference its caller may not want

        Resolve ends by parsing its assembled result into a second Reference, a heap serialization plus eight component spans, purely to establish that the bytes are well formed. A caller that stores resolved references as opaque bytes needs exactly that guarantee and none of the spans, and has no way to ask for it.

        Solution: Add a serialization-returning Resolve

        Diagnose establishes the same guarantee without constructing anything, and for URI and IRI it is the same computation Parse performs: both reduce to Analyze's error, and a successful non-web parse stores its input verbatim. Web mode normalizes, so there the normalized serialization is the result and the new form still parses to obtain it. The value equals Image of the Reference the other form returns, which the section 5.4 suite now asserts on every case it already covered.

        The two forms share a private Assemble rather than one calling the other. Composing them the obvious way, with the Reference form parsing the serialization form's result, would make it validate twice and cost it roughly 210 ns it does not pay today.

        Paired Compare in one process, release mode, against a 233-byte base: 821.3 ns/op returning a Reference against 743.4 ns/op returning a String, 9.45% less, 95% CI [1.102, 1.107], winning 100 of 100 sample pairs at an order effect of -0.46%. Isolating the validation step, Diagnose measures 211.2 ns/op against Parse's 270.1. The end-to-end saving exceeds that difference because the serialization form also skips constructing and finalizing the result Reference, not only the parse that fills it. The Reference form's median is unchanged, which is what confirms it kept its single validation.

      18. cfb25efc
        Problem: resolution assembles through a growing Unbounded_String

        Resolve merges and reduces its result by appending to an Unbounded_String, which reallocates on nearly every append, and by calling Remove_Dot_Segments, which builds a second one and returns To_String of it. Segment removal is worse than that suggests: collapsing one "/../" runs a whole To_String followed by a Set_Unbounded_String. None of this is visible in the API, and all of it is on the path of every resolution.

        Solution: Assemble into a String sized from the parsed references

        Merging and dot-segment removal never produce more than the base, the relative reference, and the separators between them, so the serialized lengths of the two parsed references bound the result. Both are real lengths rather than Max_Length, which may be Positive'Last, and both come from parsed references rather than input bytes, because web normalization can expand a relative past what it was written with. A bound above what belongs on the stack takes one exact allocation instead, which keeps a single copy of the merge rather than a rarely exercised second implementation.

        Release-mode paired medians against a 233-byte base: the Reference form falls from 823.2 to 550.4 ns and the serialization form from 743.4 to 466.5, so the change reaches the API every existing caller already uses. Resolution against an 18-byte base falls from 475.8 to 331.0. The public specification is untouched.

        A procedure form writing into a caller-supplied buffer was prototyped against this and measured 4.7% below the serialization form, winning 69 of 100 pairs. That difference is the returned copy alone, which is all the wider API buys once the assembly no longer allocates, so it is not adopted.

      19. 616fdfd5
        Problem: large resolutions overflow the stack and leak on failure

        Assembling into a buffer put four objects proportional to the reference length on the primary stack: the one-based copy of the dot-segment input, the merged path, the prefix taken out of the base path, and the result staged on the way out of the heap branch. The heap branch existed precisely so that a caller raising Max_Length would not put a large buffer on the stack, and then reached the stack anyway through the other three. Resolving a four megabyte base raised Storage_Error where the previous implementation returned a result. The heap branch also freed its buffer only on its two normal exits, so any exception through it leaked the allocation, and neither the bound nor the append guard was safe against wraparound in a body whose release profile suppresses overflow checks.

        Solution: Keep every size-proportional object off the primary stack

        Dot-segment reduction indexes its input through an offset rather than copying it one-based, so the copy is gone rather than moved. The prefix is named by bounds into the base path and written straight into the merged buffer. The merged path takes the same stack-or-heap fork as the assembly buffer, because section 5.2.4 reduces the joined path as one string and the pieces cannot be reduced separately. An extended return builds the result where the caller wants it. Both heap blocks free their allocation from an others handler as well as their normal exits.

        The append guard subtracts rather than adds, so it cannot wrap, and the bound is computed in Long_Long_Integer and rejected unless it fits Natural with room to spare, which also keeps every later index lookahead inside range.

        Resolving against bases of one hundred kilobytes, four megabytes and forty megabytes now all succeed, matching the previous implementation. A differential harness comparing both public forms against a verbatim reimplementation of the previous assembly reports no divergence over 429,208 cases, of which 105,202 raise on both sides.

      20. 18ecffdb
        Problem: the serialization Resolve overloads on result type silently

        Resolve returning String and Resolve returning Reference differ only in what they return. Most calls select between them from context, but a call whose context supplies no type does not: comparing two resolutions with "=", or taking an attribute of one, becomes ambiguous. Both were legal while only the Reference form existed, so an existing caller of the published crate meets a compiler error whose cause is not apparent from the code in front of it.

        Solution: Say so where the operation is documented

        Record the overload, name the two shapes that stop compiling, and give the disambiguation. A qualified expression settles either in place, and naming the result in a constant always works. Keeping the shared name is deliberate: the failure is a compile error rather than a silent change of meaning, and the fix is local to the call.

      21. 2f3df5f8
        Problem: the published resolution figures predate the stack fix

        BENCHMARKS.md carries medians taken before the assembly stopped staging size-proportional locals on the stack, and its comparison between the two assemblies stitches together runs from separate sittings on a host under varying load.

        Solution: Re-measure both assemblies in one interleaved sitting

        Swap the two assemblies in place across four rounds, first arm repeated as a drift control, and report the resolution rows from that. The control landed within 0.4% of itself. Removing the one-based copy from dot-segment reduction moved the figures slightly in its favour, so the buffer assembly now reads 34% below the Unbounded one for both public forms rather than 33%.

      22. 4b7b1d6c
        Problem: Admitting a reference costs a serialization copy

        Can_Parse and Diagnose report whether input parses but not how it
        classifies, so a caller that admits only absolute references -- an RDF
        crate deciding whether bytes are an absolute IRI, say -- has to reach for
        Try_Parse. Try_Parse builds a Reference, and building one stores a copy
        of a serialization that is byte for byte the input the caller already
        holds. The caller reads Kind and drops it.

        Solution: Report the classification without building the reference

        Add Inspect, which runs the analysis Try_Parse runs and reports the
        structural kind alongside the parse error. Analyze works on spans over
        the caller's String, so nothing is stored and nothing is allocated. The
        differential harness now holds Inspect to Try_Parse on both the error and
        the kind across the whole seeded corpus.

        Admitting "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" as an
        absolute IRI:

        allocs bytes ns
        via Try_Parse 1 80 145
        via Inspect 0 0 103
        -100% -100% -29%

        Measured with FLYOLOGY_IRI_BUILD_MODE=release. Both forms were run
        alternately, eight rounds each, and the minimum taken, because the host
        carries unrelated build load. Allocation counts are exact.

      23. bc3e3217
        Problem: Preprocessing copies every URL that needs no preprocessing

        Preprocess removes tab, newline and carriage return by appending the
        surviving bytes to an Unbounded_String one at a time. Almost no URL holds
        any of them, so the ordinary case takes an accumulator, grows it, and
        returns a verbatim copy of its own input.

        Solution: Return the trimmed slice when there is nothing to remove

        Scan first and build only once a byte has to be dropped, which also keeps
        the controlled accumulator out of the common path entirely. The slice is
        slid to one because Input_Offset and the parser below read the result at
        one-based offsets.

        Absolute web URLs that take the WHATWG pipeline rather than the fast
        path:

        allocs bytes ns
        web_slow, before 25 1008 2072
        web_slow, after 23 912 1964
        -8% -10% -5%

        web_idna, before 16 752 1661
        web_idna, after 14 656 1547
        -13% -13% -7%

        Measured with FLYOLOGY_IRI_BUILD_MODE=release. Revisions were built into
        separate worktrees and run alternately, eight rounds each, minimum taken,
        because the host carries unrelated build load. Allocation counts are
        exact.

        WPT URL conformance stays at 919/919 with no mismatches.

      24. bf79ef49
        Problem: Percent-encoding and decoding build their results on the heap

        Encode, Encode_Opaque_Path and Percent_Decode each accumulate into an
        Unbounded_String one character at a time and then copy the whole thing
        out with To_String. That is a heap block, the reallocations that growing
        it byte by byte implies, and one full copy, for a result whose length is
        a pure function of the input. Two of the callers encode a single
        character at a time inside a loop, so each iteration paid all of it.

        Solution: Count the result, then write it into the returned object

        Each function now measures its output in a first pass and fills an
        extended return object in a second. Since the count is exact, the
        returned String is the only storage involved -- no accumulator and no
        working buffer, so nothing is allocated and nothing is copied.

        Sizing a buffer up front was the alternative, but the bound that is known
        a priori is three bytes per input byte, and with Max_Length at one
        mebibyte that reserves three mebibytes on the stack in a crate that does
        not build with -fstack-check. Counting first costs a second pass over the
        input and reserves exactly what the result needs.

        Absolute web URLs that take the WHATWG pipeline rather than the fast
        path:

        allocs bytes ns
        web_slow, before 23 912 1964
        web_slow, after 17 720 1670
        -26% -21% -15%

        web_idna, before 14 656 1547
        web_idna, after 12 592 1449
        -14% -10% -6%

        Measured with FLYOLOGY_IRI_BUILD_MODE=release. Revisions were built into
        separate worktrees and run alternately, eight rounds each, minimum taken,
        because the host carries unrelated build load. Allocation counts are
        exact and do not depend on any of that.

        The corpus benchmark does not move: over the pinned 100,025 URLs,
        can_parse holds at 22 ns minimum and parse_href at 105 against 103, with
        acceptance identical at 99999. That corpus is dominated by URLs taking
        the allocation-free fast path, which never reach either function.

        WPT URL conformance stays at 919/919 with no mismatches, which is the
        corpus that exercises these two functions hardest.

      25. 82106435
        Problem: The API reference links to pages the generator never writes

        Since "The router's dispatch-read words share a region with writer state",
        routing.ads groups its two dispatch-read words with
        Flyology_Cachelines.Padded_Groups. That spec is one of the files the
        documentation build documents, and GNATdoc walks every project in the
        closure that Documentation.Excluded_Project_Files does not name, so the
        private with dragged the cachelines crate in with it. Its two tagged
        types, Fitted_Groups.Grouped_Array and Padded_Groups.Grouped_Array, then
        appeared in the index's tagged-type section, each linked to a page of its
        own -- and GNATdoc writes a page per tagged type only under
        --html-oop-style, which this build does not pass. This crate's own tagged
        types are linked as unit page plus fragment and resolve; those two never
        could.

        The site check reports both as missing targets, so the Pages workflow has
        failed on every push to main since that commit landed and the published
        site is frozen at the last green deploy. CI is unaffected: the two
        workflows fail independently, and only one of them was ever red.

        Solution: Document this crate and nothing else

        Name every dependency in Excluded_Project_Files, beside the Flyology
        runtime that was already there. Excluding cachelines alone would clear the
        two broken links, but the closure walk is why they were reachable at all,
        and the same walk had already put twenty-four pages of QUIC and allocator
        internals into a reference whose own footer reads "Public HTTP API only".
        The index now lists this crate's sixty-two entries, the search index
        carries 2441 names with none from a dependency, and no page outside
        Flyology.HTTP is written.

        Removing those pages breaks no link. Their only inbound references were
        the index entries that go away with them: scanning every website page and
        every generated page for their file names finds nothing else pointing at
        them.

        Each exclusion names its project through the prefix Alire exports for that
        crate rather than a path under FLYOLOGY_ROOT. The Flyology crate vendors
        copies of the cachelines and allocator sources, so the two resolve to
        different build directories, and GNATdoc rejects an excluded file that is
        not the project it loaded -- "unable to resolve project file path", a hard
        error rather than a silent no-op, so naming the vendored copy fails the
        run outright. A bare project name fails the same way.

        Verified with docs/api deleted first, since the workflow builds from a
        fresh checkout and a stale page left behind by an earlier run would hide a
        link the workflow cannot resolve. scripts/build-site.sh, which is what the
        workflow runs, reports "Site check passed: 70 HTML files and 136 total
        files".

        Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

      26. 83db8c4d
        Problem: A discarded QUIC Initial ends the HTTP/3 integration exchange

        The dual-stack overload of Routing.Serve divides HTTP_3_Capacity between the
        address families, so HTTP_3_Capacity => 8 gave each listener four connection
        slots rather than eight. Both client profiles in this test address
        "localhost", which resolves to every loopback family on some hosts, and the
        client's connection race completes a full QUIC handshake on each family
        before it discards the losing lane. Each family therefore admits up to five
        concurrent connections here: two live client profiles, two losing race lanes
        awaiting release, and the raw Initial. Instrumented runs reach four of four
        slots routinely.

        A listener whose registry is full discards an Initial without answering it,
        and no handshake-space probe timeout retransmits one. The raw handshake loop
        compounded that: its receive raised Flyology.IO.Timeout_Error straight out of
        the loop, so the eight attempts were never a retry budget and the first quiet
        interval ended the run. The response loop had the same shape. Sizing a run of
        twenty at each capacity reproduced the failure in nineteen runs at two slots
        per family, seven at three, and one at four, tracking the discarded Initials
        one for one.

        Solution: Retransmit the handshake flight and size the listener for the load

        Retain the last flight sent to the server and resend it when a receive
        expires, spending the attempt budget on eight two-second probes rather than
        one ten-second wait. The response loop keeps its budget for waiting, because
        the server does drive application-space probe timeouts and retransmits on its
        own; sixteen one-second probes stay inside the server's connection age.
        Neither loop now ends an exchange on a single discarded datagram.

        Raise HTTP_3_Capacity to sixteen and record the actual per-family model in
        the comment, so the test stops running its listeners at full occupancy by
        accident. With the retransmission in place the capacity is no longer load
        bearing: at two slots per family, where the previous loop failed nineteen
        runs of twenty, the raw handshake now completes in all twenty.

        This is a test change. The absent handshake-space probe timeout is a real gap
        in the QUIC layer and is not addressed here.

      27. d7d87344
        Problem: A QUIC endpoint cannot close before its handshake completes

        CONNECTION_CLOSE is only reachable through the application space. An endpoint
        that abandons a connection while it still holds Initial or Handshake keys has
        no way to say so, and Build_Application_Close_Datagram's precondition rules it
        out.

        The receiving side is missing too. Initial_Space and Handshake_Space parse a
        peer Transport_Close frame, count it, and discard it. A peer that did somehow
        send one would be ignored, so adding a builder alone would change nothing
        observable.

        Solution: Report a peer close from both spaces and expose a close builder

        Initial_Space and Handshake_Space now carry Peer_Closed and Close_Error in
        their Process_Result and stop parsing at the frame, since RFC 9000 10.2.2 puts
        the receiver into the draining state and the rest of the packet cannot change
        that. Connection_Driver acts on it exactly as it already does for the
        application space: Peer_Closed state, Connection_Closed status.

        Build_Handshake_Close_Datagram builds the outbound half in the highest space
        the connection holds, Handshake once that space exists and Initial otherwise,
        so a peer that reached either level can read it. It carries the transport
        APPLICATION_ERROR code that RFC 9000 10.2.3 reserves for an application close
        that its encryption level cannot express, and leaves the connection Failed
        because an endpoint that has begun closing must send nothing else.

        Initial_Space.Build_Transport_Close_Packet passed a zero minimum packet length
        for both roles, so a client-sent Initial close fell under 1,200 bytes and RFC
        9000 14.1 requires a server to discard it. It now derives the minimum from the
        role, as Build_Crypto_Packet already did. That also corrects the existing
        client Fail_Initial_With_Close path, whose closes were unreadable for the same
        reason.

      28. c041b36d
        Problem: A lane that loses the address-family race abandons its handshake

        For HTTP/3 both lanes of the address-family race run Start_Connection, which
        completes a full QUIC handshake before Race.Choose picks a winner. The loser
        raises Connection_Race_Lost, Close_Candidate runs, and Dispose_Connection sends
        an application CONNECTION_CLOSE only when the transport reached the connected
        state. A lane cancelled mid-handshake never did, so the client closes its UDP
        socket and says nothing.

        The server is left waiting for a handshake that will never arrive. On a bounded
        listener that costs a connection slot for the whole handshake timeout, and a
        peer that repeatedly starts and abandons handshakes can hold every slot.

        Solution: Send a handshake-space close from the abandoned lane

        Dispose_Connection now picks the close by transport state rather than skipping
        it: an application close when connected, and Build_Handshake_Close_Datagram
        when the connection is still in Client_Initial or Client_Handshake. Both go out
        on the connection's own UDP socket before it closes, and both remain best
        effort, since a disposal path cannot report a send failure to anyone.

      29. fe4a9d4d
        Problem: A silent peer holds a listener slot for the whole handshake timeout

        Serve_Connection waits for QUIC.Is_Connected against one deadline, the absolute
        handshake timeout measured from the connection epoch. A peer that sends an
        Initial and then stops answering is indistinguishable from one that is merely
        slow, so its worker waits out the full budget and its Connection_Registry slot
        stays taken. A cooperative peer now sends a close, but a crashed, partitioned,
        or hostile one still does not.

        Solution: Deadline an unconnected peer on no progress as well as elapsed time

        Connection_State records the arrival of each inbound datagram, and the
        pre-handshake wait takes the earlier of the absolute handshake deadline and
        that arrival plus Handshake_Idle_Timeout. The absolute budget still bounds a
        peer that keeps sending; the no-progress budget reclaims the slot from one that
        stops.

        Default_Handshake_Idle_Timeout is three seconds. Handshake retransmission on a
        lossy path arrives well inside that window and counts as progress, so only a
        silent peer reaches it. Serve_Listener and both Serve overloads take an
        override. Routing.Serve is left alone: it gets the shorter reclamation from the
        default without adding a parameter to eight overloads.

      30. 439a9fb6
        Problem: Nothing checks that an abandoned handshake frees its listener slot

        Both reclamation paths, the peer's transport CONNECTION_CLOSE and the server's
        no-progress deadline, are only observable as the absence of a stall. No test
        saturates a bounded listener with half-open handshakes, so either could regress
        into the ten-second wait it replaced without a failure anywhere.

        Solution: Saturate a listener of capacity N and require a fresh Initial

        http3_handshake_abandon runs two phases against a capacity-three listener whose
        handshake timeout is twenty seconds, far beyond every deadline it asserts, so a
        slot reclaimed inside one of them cannot be explained by that timeout. Each
        phase fills every slot with a handshake that will not complete, asserts that a
        further probe is refused, releases the lanes, and then requires a fresh Initial
        to be admitted.

        The first phase abandons with closes and leaves the no-progress deadline out of
        range; the second goes silent and relies on the deadline alone. Odd lanes
        consume the ServerHello first so they abandon from the Handshake space, while
        even lanes abandon from the Initial space, covering both protection levels. The
        probe repeats its Initial while no worker answers, the way a real client's probe
        timeout would, so a slot released partway through the budget is still taken up.

        Each phase was confirmed to fail on its own: removing the driver's peer-close
        reporting fails the first, and dropping the no-progress term from the deadline
        fails the second.

    3. 439a9fb6 updated to dac7fa90index 377df96f

      2 source commits

      1. a3866c57
        Problem: A lost handshake datagram stalls the connection until it times out

        Flyology.QUIC.Connections exposes loss recovery only for the application
        packet-number space. The Initial and Handshake spaces track nothing they
        have sent, discard the peer's ACK frames after parsing them, and never
        acknowledge an ack-eliciting Initial or Handshake packet, which RFC 9000
        13.2.1 requires immediately. Nothing arms the RFC 9002 6.2 probe timeout
        those spaces need.

        Both HTTP/3 drivers inherit the gap. Start_Connection loops on Receive_One
        until the transport connects and Serve_Connection waits up to
        Handshake_Timeout for progress; neither retransmits its own flight. A single
        dropped client Initial or dropped server flight therefore costs the caller's
        whole deadline rather than one probe timeout, which is how an ordinary
        transient loss became a hard CI failure in the raw handshake lane of
        tests/http3_server_integration.adb. That lane now works around the gap by
        resending its own flight; the gap itself is still open.

        Solution: Give the Initial and Handshake spaces RFC 9002 loss recovery

        Each space now owns a sent-packet ledger and retains the CRYPTO ranges it
        has sent in Crypto_Flight, so a probe can rebuild a range under a fresh
        packet number rather than resending a packet QUIC forbids repeating. Peer
        ACK frames drive Sent_Packet_Policy.Apply_ACK and yield the delivery, loss,
        and RTT events the spaces previously threw away. Every packet a space builds
        carries the acknowledgment it owes, and a datagram that produces no response
        sends an ACK-only packet, so a peer's probe timeout clears within one round
        trip.

        Connection_Driver holds one path-wide Recovery_Policy state for both spaces:
        a single probe count backing off together, and a probe timeout that excludes
        max_ack_delay because handshake packets are acknowledged immediately.
        Has_Recovery_Timeout, Recovery_Deadline, and Process_Timeout now report the
        earlier of the handshake and application deadlines, and an expired handshake
        timeout retransmits every unacknowledged CRYPTO range. A client whose peer
        has not completed address validation sends the 6.2.2.1 anti-deadlock probe
        instead. Progress that can only follow delivery of a flight retires it
        without waiting for an ACK.

        The HTTP/3 drivers needed almost nothing. Both already bounded each receive
        by Recovery_Deadline and processed an expired timer, so widening the timer to
        cover the handshake spaces made their loops retransmit; Start_Client gained a
        defaulted Now so the timer has an anchor.

        The raw QUIC lane of the server integration test carried a stand-in for this
        gap: it retained the last flight it sent and resent it when a receive expired,
        because nothing below the test retransmitted. The transport owns that now, so
        the lane drives Process_Timeout against its own clock and the retained flight
        is gone. Its listener sizing and the patience of its response loop are
        unchanged, since neither depended on the missing timeout.

        Handshake-space congestion is accounted but never gates a send: the flight
        is far below the initial window and RFC 9002 permits probing regardless.
        Immediate acknowledgment costs one extra packet per silent datagram,
        including a padded client Initial ACK when only the ServerHello arrives;
        that is what lets a peer stop retransmitting after one round trip.

        Two new tests cover the loss. A deterministic transport test drives an
        explicit clock through a dropped client Initial, a dropped server Handshake
        flight, and the anti-deadlock probe, checking the exact first deadline, the
        doubled backoff, and that an already-acknowledged Initial flight is not
        retransmitted. An end-to-end test puts the routed server and the standard
        client either side of a UDP relay that swallows one flight; with the probe
        timer disabled it stalls for the full deadline and fails.

      2. dac7fa90
        Problem: The QUIC pin hides which version dependents need

        The sibling checkout pinned for local development also stood in for the QUIC
        dependency's version, leaving it declared as "*". Local builds resolve through
        the pin and never notice, but the pin cannot cross into the index, so anything
        depending on this crate is free to resolve any QUIC release at all.

        Solution: Declare the version the pin stands in for

        Constrain the dependency to the development line the pinned checkout provides,
        so the same version is selected once the pin is gone.

        Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

    Compare source revisions
  32. Advance development source pins

    c124f3e3 on GitHub
  33. Development entries for flyology_rdf, flyology_n3 and

    2730c85f on GitHub
  34. Publish the numa development manifest

    5f7622a7 on GitHub
  35. Publish the allocators development manifest

    b6c5fcbb on GitHub
  36. open the indexed 0.1.1 development cycle

    8bece74f on GitHub
  37. Publish validated tagged crate releases

    981209ad on GitHub
  38. Publish validated tagged crate releases

    d4fb5506 on GitHub
  39. Publish validated tagged crate releases

    eb2fea94 on GitHub
  40. Publish validated tagged crate releases

    2820c41c on GitHub
  41. Publish validated tagged crate releases

    cd3679c0 on GitHub
  42. Publish validated tagged crate releases

    6d1ac914 on GitHub
  43. Publish validated tagged crate releases

    53def6c7 on GitHub
  44. import validated gnat_flyology_native manifests

    37eb0e5e on GitHub
  45. import validated gnat_flyology_native manifests

    fd3f3c65 on GitHub
  46. import validated gnat_flyology_native manifests

    b2a6ba64 on GitHub