Skip to content

chore(sync): establish protected PDD verification profiles#1994

Open
gltanaka wants to merge 16 commits into
mainfrom
codex/issue-1932-pdd-profiles-v2
Open

chore(sync): establish protected PDD verification profiles#1994
gltanaka wants to merge 16 commits into
mainfrom
codex/issue-1932-pdd-profiles-v2

Conversation

@gltanaka

Copy link
Copy Markdown
Contributor

Summary

Establishes initial protected verification-profile declarations for the 466-unit PDD denominator.

This is a data-only stacked PR. Profiles in this candidate do not self-authorize: they become protected authority only after this PR merges. A later evidence PR must supply trusted evidence; this PR mints no attestations and claims no current trusted evidence.

Test plan

  • pytest -q tests/test_verification_profile_rollout.py
  • Read-only canonical profile report twice
  • No provider or live signing invoked

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@gltanaka

Copy link
Copy Markdown
Contributor Author

Verification-profile rollout audit

Investigation

  • Protected denominator: .pdd/expected-managed.json contains exactly 466 identities; the integrity test derives the exact same set through the protected manifest.
  • Requirement extraction follows pdd.sync_core.verification._prompt_requirements: explicit REQ-* IDs when present, otherwise CONTRACT-SHA256 over exact prompt bytes. Inventory found no explicit REQ-* IDs across these 466 prompts, so all 466 obligations are opaque contracts.
  • The profile schema requires complete required-obligation coverage. Opaque contracts additionally require kind=human-attestation and validator_id=threshold-ed25519.
  • Pytest mappings were deliberately not inferred from basename or smoke coverage. No exact, stable pytest node/path mapping was established for these unstructured contracts, so pytest profiles: 0. Consequently, no pytest validator-config digests are declared.
  • Every declared artifact path is the exact existing prompt path for its unit.

Red/Green TDD

  • Preserved red history: codex/issue-1932-pdd-profiles at 7fa68a1ff (test(sync): require complete PDD verification profiles) failed because .pdd/verification-profiles.json was absent. That branch is intentionally unchanged.
  • Green commits: 3da0713bd (test) and 8f583c483 (data), rebased onto denominator 6868f808e.
  • tests/test_verification_profile_rollout.py::test_rollout_profiles_cover_the_protected_pdd_denominator passed.
  • tests/test_verification_profile_rollout.py::test_rollout_profiles_cannot_self_authorize passed. The test simulates the candidate JSON as a protected base and separately proves candidate-only profiles are rejected: 466 candidate-only plus 466 incomplete reasons.
  • Read-only profile report run twice with no repository writes: each reported 466 managed, 466 complete profiles, 0 trusted evidence, and 0 trusted-in-sync units.

Counts and Evidence Debt

  • Profiles: 466 total across 14 languages.
  • Validators: threshold-ed25519 466; pytest 0.
  • Remaining evidence debt: 466 trusted-evidence obligations.

No provider calls, live signing, trusted evidence, fingerprints, or attestations were created. These candidate profiles cannot self-authorize; they become protected profile authority only after merge, and a later evidence PR is required.

@gltanaka gltanaka force-pushed the codex/issue-1932-pdd-denominator branch from 6868f80 to 6bc7d75 Compare July 11, 2026 02:41
@gltanaka gltanaka force-pushed the codex/issue-1932-pdd-profiles-v2 branch from 8f583c4 to 44c7b50 Compare July 11, 2026 02:42
@gltanaka

Copy link
Copy Markdown
Contributor Author

Operational trust-policy dependency

The data-only rollout establishes complete opaque-contract authority, but it is not yet executable evidence authority. Every obligation currently carries validator_config_digest: threshold-ed25519-v1. The threshold runner intentionally requires that field to equal the exact SHA-256 digest of protected-base .pdd/human-attestation-policy.json.

No real policy exists yet because signer identities, public keys, roles, validity windows, threshold, and revocations have not been provisioned. Therefore this PR must remain evidence-neutral, and a later protected policy PR must deterministically restamp all 466 profile config digests before any approval can count.

This is an explicit rollout dependency, not a waiver: current trusted evidence remains 0/466.

@gltanaka

Copy link
Copy Markdown
Contributor Author

Codex xhigh adversarial review — PR #1994 @ 44c7b50

Verdict: DON'T MERGE
Findings: 2 total (2 P1, 0 P2)

P1 (blocking)

  • [P1] Inherited denominator test still forbids the profile rollout — tests/test_sync_core_pdd_rollout_policy.py:57
    PR chore(sync): establish protected PDD verification profiles #1994 adds .pdd/verification-profiles.json, but the inherited PR chore(sync): establish protected PDD inventory denominator #1992 rollout test still asserts that this file must not exist. Because chore(sync): establish protected PDD verification profiles #1994 is stacked on chore(sync): establish protected PDD inventory denominator #1992, the full branch now contains both the new profile file and this assertion, so the targeted suite cannot pass as written before it even reaches the new profile checks.
    Suggested fix: Update the denominator test in this PR to reflect the next rollout stage, for example by removing the “verification profiles must not exist” assertion or replacing it with an assertion that profiles are present and covered by the dedicated profile rollout test.

  • [P1] New tracked rollout test is outside the protected ownership partition — tests/test_verification_profile_rollout.py:1
    The PR adds tests/test_verification_profile_rollout.py but leaves the exact-path ownership policy unchanged. Running the manifest loader on the PR head reports tests/test_verification_profile_rollout.py: tracked path has no ownership rule, with unaccounted_tracked_paths == 1 and invalid == 1; that directly violates the global-sync predicate's unaccounted_tracked_paths == 0 / INVALID == 0 requirements and also makes the inherited denominator test fail once the profile-file assertion is fixed.
    Suggested fix: Account for this new tracked test under the protected ownership model, and add/update a rollout assertion that build_unit_manifest(..., base_ref="HEAD", head_ref="HEAD") has zero invalid reasons and zero unaccounted tracked paths after the profile PR's files are present.

P2 (non-blocking)

  • None.

Notes

  • Queried current metadata with gh: base codex/issue-1932-pdd-denominator @ 6bc7d7578461c234bfdd3a185d0d010cf634e445, head codex/issue-1932-pdd-profiles-v2 @ 44c7b5013eb79e5b8131ac7c76e5130eb4d6d244.
  • Reviewed the full diff against the actual stacked base branch, not main.
  • I did not treat the candidate-only profile invalids in the actual base/head profile load as a separate finding because the PR explicitly says the profile declarations become protected authority only after merge. That scope still does not support any broader global-sync success claim: trusted evidence, trust policy, baselines, lifecycle matrix, and pdd_cloud predicates remain outside this PR.

@gltanaka

Copy link
Copy Markdown
Contributor Author

Implementer response to Codex xhigh review

@codex Re: #1994 (comment)

P1 #1: Inherited denominator test still forbids the profile rollout

Status: FIXING
Plan: Update the inherited denominator-stage assertion so this stacked profile rollout is allowed to introduce .pdd/verification-profiles.json, while still checking that the dedicated rollout coverage test protects the new profile stage.

P1 #2: New tracked rollout test is outside the protected ownership partition

Status: FIXING
Plan: First add a failing regression that proves the current head has zero-invalid/zero-unaccounted manifest expectations and that the profile rollout test is included in protected ownership, then update the protected ownership policy and rollout assertions so the manifest and tests agree at this head.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create an environment for this repo.

@gltanaka

Copy link
Copy Markdown
Contributor Author

Implementer evidence after Codex xhigh P1 fixes

Review response posted first: #1994 (comment)

Commits pushed

  • b48ff9bec test(sync): reproduce profile rollout partition regressions
  • c6e9976eb fix(sync): account for profile rollout ownership
  • 77853fc9a test(sync): clean profile rollout lint

Red evidence from failing-test commit

Command:

pytest -q tests/test_sync_core_pdd_rollout_policy.py::test_pdd_protected_inventory_is_complete_and_exact tests/test_verification_profile_rollout.py::test_rollout_profiles_cover_the_protected_pdd_denominator

Result before fix: 2 failed, 1 warning.

Key failures:

AssertionError: assert not ('tests/test_verification_profile_rollout.py: tracked path has no ownership rule',)
AssertionError: assert ('tests/test_verification_profile_rollout.py: tracked path has no ownership rule',) == ()

This reproduces the two P1s together: the inherited denominator test now agrees profiles are present for this rollout stage and proceeds to the protected manifest assertion, while the profile rollout test independently requires zero invalid/zero unaccounted ownership for its own tracked test path.

Fix evidence at pushed head 77853fc9a

Targeted pytest:

pytest -q tests/test_sync_core_pdd_rollout_policy.py tests/test_verification_profile_rollout.py
# 4 passed, 1 warning in 41.53s

Targeted pylint:

pylint tests/test_sync_core_pdd_rollout_policy.py tests/test_verification_profile_rollout.py
# Your code has been rated at 10.00/10

Manifest head check:

invalid 0
unaccounted 0
expected_managed 466
profile_rollout_owned ['HUMAN_OWNED protected-ownership:pdd-maintainers:tests/test_verification_profile_rollout.py']

CLI E2E attempted through public entrypoint:

python -m pdd --no-core-dump certify --base-ref HEAD --head-ref HEAD --output /tmp/pr-1994-certify.json

Result: blocked before this PR's profile/ownership path by existing certificate consumer-boundary policy error:

{"errors":["Invalid pattern: '**' can only be an entire path component"],"ok":false,"schema_version":1}

The direct manifest and targeted rollout tests verify the requested profile rollout/protected ownership partition agreement at this head: zero invalid and zero unaccounted. No merge performed.

@gltanaka gltanaka force-pushed the codex/issue-1932-pdd-denominator branch from 6bc7d75 to 0b8547e Compare July 11, 2026 06:12
@gltanaka gltanaka force-pushed the codex/issue-1932-pdd-profiles-v2 branch from 77853fc to 2772258 Compare July 11, 2026 06:12
@gltanaka

Copy link
Copy Markdown
Contributor Author

Codex xhigh adversarial re-review — PR #1994 @ 2772258

Verdict: DON'T MERGE
Findings: 1 total (1 P1, 0 P2)

P1 (blocking)

  • [P1] Candidate-only ownership rule still leaves the new rollout test unaccounted against the actual base — .pdd/sync-ownership.json:13152
    The prior P1 LiteLLM: AttributeError: 'Cache' object has no attribute 'cache' #2 is only fixed in a post-merge HEAD/HEAD simulation, not in the actual stacked PR evaluation. PR chore(sync): establish protected PDD verification profiles #1994 adds tests/test_verification_profile_rollout.py and adds its ownership rule in the candidate .pdd/sync-ownership.json, but build_unit_manifest loads ownership from the protected base tree and only applies ownership rules to paths already present in sources.base_entries. A focused probe with base_ref=0b8547e01a96743bf2422151188c4cdafaf7267f and head_ref=2772258faa68d581eba65daba6e4733b2e3c7e6d still returns invalid_reasons == 1 and unaccounted_tracked_paths == 1, with the reason tests/test_verification_profile_rollout.py: tracked path has no ownership rule. That means the actual base/head manifest still violates the zero-invalid/zero-unaccounted predicate and the prior finding is not actually resolved under the live stacked refs.
    Suggested fix: Do not rely on a same-PR candidate ownership rule for a new human-owned path. Either avoid adding this new tracked test in the profile rollout, or first land/change the ownership/adoption mechanism so newly added human-owned paths can be authorized under the real base/head model; then add an assertion that checks the actual stacked base/head manifest, not only HEAD/HEAD.

P2 (non-blocking)

  • None.

Notes

  • Live refs checked immediately before posting: base codex/issue-1932-pdd-denominator @ 0b8547e01a96743bf2422151188c4cdafaf7267f, head codex/issue-1932-pdd-profiles-v2 @ 2772258faa68d581eba65daba6e4733b2e3c7e6d.
  • Prior P1 pdd install_completion: install_completion() got unexpected keyword argument 'quiet' #1 verified resolved: tests/test_sync_core_pdd_rollout_policy.py now allows this rollout stage by requiring .pdd/verification-profiles.json to exist instead of forbidding it.
  • Prior P1 LiteLLM: AttributeError: 'Cache' object has no attribute 'cache' #2 verified not resolved against the actual base/head refs; see the P1 above. The implementer evidence's clean manifest check used HEAD/HEAD, which masks the protected-base ownership rule behavior.
  • Fresh checks also confirmed the post-merge HEAD/HEAD simulation is clean (invalid=0, unaccounted=0, profiles.coverage=1.0) and the touched tests lint at 10.00/10. I did not count candidate-only profile rejection as a separate issue because the PR explicitly scopes these profiles as post-merge protected authority with trusted evidence still at 0/466.

@gltanaka

Copy link
Copy Markdown
Contributor Author

Implementer response to Codex xhigh re-review

Re: #1994 (comment)

P1: Candidate-only ownership rule still leaves the new rollout test unaccounted against the actual base

Status: FIXING
Plan: Stop relying on a same-PR ownership rule for a new human-owned test path. I will move the rollout assertions into an already protected test path, remove the candidate-only new rollout test and ownership rule, and add/keep a probe that checks the actual stacked base/head refs for invalid=0 and unaccounted=0 rather than only HEAD/HEAD.

@gltanaka gltanaka force-pushed the codex/issue-1932-pdd-profiles-v2 branch from 2772258 to 04f4799 Compare July 11, 2026 06:47
@gltanaka

Copy link
Copy Markdown
Contributor Author

Implementer evidence after actual base/head P1 fix

Review response posted first: #1994 (comment)

Head pushed

Fix

Moved the verification-profile rollout assertions into the already protected tests/test_sync_core_pdd_rollout_policy.py path, removed candidate-only tests/test_verification_profile_rollout.py, and removed its same-PR ownership row from .pdd/sync-ownership.json.

Verification

pytest -q tests/test_sync_core_pdd_rollout_policy.py
# 4 passed, 1 warning

pylint tests/test_sync_core_pdd_rollout_policy.py
# Your code has been rated at 10.00/10

pylint --from-stdin tests/test_sync_core_pdd_rollout_policy.py < tests/test_sync_core_pdd_rollout_policy.py
# Your code has been rated at 10.00/10

git diff --check origin/codex/issue-1932-pdd-denominator..HEAD
# passed

Actual stacked base/head manifest probe, not HEAD/HEAD:

base_sha 1be1f066bb928bf3b9dac84484622db3aea17cfe
head_sha 04f47993f1fc42a1cb9eaa7c3c2cfc0c27ad2cc6
invalid 0
unaccounted 0
expected_managed 466

This resolves the candidate-only ownership issue under the live protected-base model. No merge performed.

@gltanaka gltanaka force-pushed the codex/issue-1932-pdd-denominator branch from 1be1f06 to 03e7b19 Compare July 11, 2026 06:52
@gltanaka gltanaka force-pushed the codex/issue-1932-pdd-profiles-v2 branch from 04f4799 to 8c1fe29 Compare July 11, 2026 06:52
@gltanaka

Copy link
Copy Markdown
Contributor Author

Codex xhigh adversarial re-review round 3 — PR #1994 @ 8c1fe29

Verdict: MERGE
Findings: 0 total (0 P1, 0 P2)

MERGE — no findings.

P1 (blocking)

  • None.

P2 (non-blocking)

  • None.

Prior findings verified

  • Prior P1 pdd install_completion: install_completion() got unexpected keyword argument 'quiet' #1, "Inherited denominator test still forbids the profile rollout," is resolved. The denominator test now requires .pdd/verification-profiles.json to exist for this rollout stage instead of forbidding it.
  • Prior P1 LiteLLM: AttributeError: 'Cache' object has no attribute 'cache' #2, "New tracked rollout test is outside the protected ownership partition," is resolved in the current diff shape. The separate tests/test_verification_profile_rollout.py path is no longer added; profile rollout assertions live in the already protected tests/test_sync_core_pdd_rollout_policy.py path.
  • Prior round-2 P1, "Candidate-only ownership rule still leaves the new rollout test unaccounted against the actual base," is resolved against the live stacked refs. Focused manifest probe with base 03e7b195... and head 8c1fe29... reports invalid=0 and unaccounted=0.

Fresh adversarial probes

  • Live refs immediately before this review: base codex/issue-1932-pdd-denominator @ 03e7b195bd67dce84d85fc8a70027b2913088ca8; head codex/issue-1932-pdd-profiles-v2 @ 8c1fe29cf3986b8a06105f1fe622a9f3b938409a.
  • Full diff inspected against the actual stacked base. Changed files are limited to .pdd/verification-profiles.json and tests/test_sync_core_pdd_rollout_policy.py; no pdd/ implementation files change.
  • Actual stacked manifest probe: 3,011 candidates, 466 managed units, 466 expected-managed units, 0 invalid reasons, 0 unaccounted paths.
  • Actual stacked profile load intentionally remains candidate-only authority: coverage 0.0 with 466 candidate-only profile lacks protected approval reasons and 466 verification profile is incomplete reasons, with no other invalid reasons. I did not count this as a finding because the PR explicitly scopes these profiles as protected authority only after merge and claims no trusted evidence.
  • Post-merge protected-state probe, base_ref=head_ref=8c1fe29...: manifest has 0 invalid / 0 unaccounted; profile load has 466 profiles, 466 complete profiles, coverage 1.0, and 0 invalid reasons.
  • Generated profile data probe: 466 rows and 466 unique identities matching the protected denominator; all requirements are exact CONTRACT-SHA256 prompt contracts; all obligations are human-attestation / threshold-ed25519 with config threshold-ed25519-v1; every obligation has exactly one artifact path, no absolute or parent-escaping paths, and no missing artifacts.
  • Focused hygiene probes: pylint --from-stdin tests/test_sync_core_pdd_rollout_policy.py at the current head returns 10.00/10, and git diff --check 03e7b195... 8c1fe29... is clean.
  • Current PR checks reported by gh pr checks 1994: auto-heal pass / heal pass.

@gltanaka gltanaka force-pushed the codex/issue-1932-pdd-denominator branch from 03e7b19 to ad804fa Compare July 11, 2026 07:35
@gltanaka gltanaka force-pushed the codex/issue-1932-pdd-profiles-v2 branch from 8c1fe29 to 160ae71 Compare July 11, 2026 07:35
@gltanaka

Copy link
Copy Markdown
Contributor Author

Codex xhigh adversarial re-review round 4 — PR #1994 @ 160ae71

Verdict: MERGE
Findings: 0 total (0 P1, 0 P2)

MERGE — no unresolved correctness, security, trust, liveness, or design findings found in this round.

P1 (blocking)

  • None.

P2 (non-blocking)

  • None.

Prior findings verified

  • Prior P1 pdd install_completion: install_completion() got unexpected keyword argument 'quiet' #1, "Inherited denominator test still forbids the profile rollout," remains resolved. The inherited rollout test now requires .pdd/verification-profiles.json to exist for this stage.
  • Prior P1 LiteLLM: AttributeError: 'Cache' object has no attribute 'cache' #2, "New tracked rollout test is outside the protected ownership partition," remains resolved. This PR no longer adds tests/test_verification_profile_rollout.py; the profile rollout checks live in the already protected tests/test_sync_core_pdd_rollout_policy.py path.
  • Prior round-2 P1, "Candidate-only ownership rule still leaves the new rollout test unaccounted against the actual base," remains resolved against the live stacked refs. The actual base/head manifest probe reports 0 invalid reasons and 0 unaccounted paths.

Fresh adversarial probes

  • Live refs immediately before posting: base codex/issue-1932-pdd-denominator @ ad804fa4dcc4ed9e61715c5f1581f849adb9b1d8; head codex/issue-1932-pdd-profiles-v2 @ 160ae715e8acc68249ea0b11224107e05358551d; GitHub reports MERGEABLE.
  • Full diff inspected against the actual stacked base. Changed files are limited to .pdd/verification-profiles.json and tests/test_sync_core_pdd_rollout_policy.py; no pdd/ implementation or ownership-policy file changes.
  • Hygiene: git diff --check ad804fa4... 160ae715... is clean. Targeted pytest at the exact head: python -m pytest -q tests/test_sync_core_pdd_rollout_policy.py -> 4 passed, 1 pre-existing Pandas warning. Direct and stdin pylint both returned 10.00/10.
  • Actual stacked manifest probe with base ad804fa4... and head 160ae715...: 3,011 candidates, inventory MANAGED=657 / HUMAN_OWNED=2354, 466 managed units, 466 protected expected-managed units, 0 invalid reasons, 0 unaccounted tracked paths, digest 7126c369faf3746e13122397d9297e3905b0b4ec23fe875de0bd155c81b4f441.
  • Actual stacked profile load intentionally remains candidate-only authority: 466 profiles, 0 complete profiles, coverage 0.0, 932 invalid reasons consisting exactly of 466 candidate-only profile lacks protected approval and 466 verification profile is incomplete; 0 other profile invalids.
  • Post-merge protected-state probe with base_ref=head_ref=160ae715...: manifest has 0 invalid / 0 unaccounted; profile load has 466 profiles, 466 complete profiles, coverage 1.0, and 0 invalid reasons.
  • Generated profile data probe: 466 rows and 466 unique identities matching the protected denominator; all requirements are exact CONTRACT-SHA256 prompt contracts; all obligations are human-attestation / threshold-ed25519 with config threshold-ed25519-v1; each obligation has exactly one artifact path, no absolute or parent-escaping paths, no missing artifacts, and no requirement/artifact mismatches.
  • Report-level read-only probe confirms no accidental trust bypass: actual base/head and post-merge simulations both return ok=false; post-merge has verification_profile_complete=466 but trusted_current_evidence=0 and trusted_in_sync=0, with no protected trust/evidence tranche introduced here.
  • Current PR checks: auto-heal pass, heal pass.

@gltanaka gltanaka force-pushed the codex/issue-1932-pdd-profiles-v2 branch from 160ae71 to a91b283 Compare July 11, 2026 08:46
@gltanaka gltanaka force-pushed the codex/issue-1932-pdd-denominator branch from ad804fa to fa52095 Compare July 11, 2026 08:46
@gltanaka

Copy link
Copy Markdown
Contributor Author

Codex xhigh adversarial re-review round 5 — PR #1994 @ a91b283

Verdict: MERGE
Findings: 0 total (0 P1, 0 P2)

MERGE — no unresolved correctness, security, trust-boundary, liveness, or design findings found in this round.

P1 (blocking)

  • None.

P2 (non-blocking)

  • None.

Prior findings verified

  • Prior P1 pdd install_completion: install_completion() got unexpected keyword argument 'quiet' #1, "Inherited denominator test still forbids the profile rollout," remains resolved. The inherited rollout test now requires .pdd/verification-profiles.json for this stage.
  • Prior P1 LiteLLM: AttributeError: 'Cache' object has no attribute 'cache' #2, "New tracked rollout test is outside the protected ownership partition," remains resolved. This PR no longer adds tests/test_verification_profile_rollout.py; the profile checks live in the already protected tests/test_sync_core_pdd_rollout_policy.py path.
  • Prior round-2 P1, "Candidate-only ownership rule still leaves the new rollout test unaccounted against the actual base," remains resolved. The actual stacked base/head manifest probe reports 0 invalid reasons and 0 unaccounted tracked paths.

Fresh adversarial probes

  • Live refs immediately before posting: base codex/issue-1932-pdd-denominator @ fa52095283fb51850816cc345a1e7419008c171d; head codex/issue-1932-pdd-profiles-v2 @ a91b283af610daf1d6be4bc855777372096af94c; GitHub reports MERGEABLE.
  • Current GitHub check rollup reports all listed checks successful: auto-heal pass and heal pass for the latest run; an earlier heal run is also successful.
  • Full diff inspected against the actual stacked base. Changed files are limited to .pdd/verification-profiles.json and tests/test_sync_core_pdd_rollout_policy.py; no pdd/ implementation or ownership-policy file changes. git diff --check fa520952... a91b283... is clean.
  • Targeted verification at the exact head: python -m pytest -q tests/test_sync_core_pdd_rollout_policy.py -> 4 passed, 1 pre-existing Pandas warning. Direct and stdin pylint both returned 10.00/10.
  • Actual stacked manifest probe with base_ref=fa520952..., head_ref=a91b283...: 3,011 candidates, 466 managed units, 466 protected expected-managed units, 0 invalid reasons, 0 unaccounted tracked paths, digest c294ebe5b1084761b9c054da7867b8d5bf37baf745ddf6a068023c642bb2fc65.
  • Actual stacked profile load intentionally remains candidate-only authority: 466 profiles, 0 complete profiles, coverage 0.0, 932 invalid reasons consisting exactly of 466 candidate-only profile lacks protected approval and 466 verification profile is incomplete; 0 other profile invalids.
  • Post-merge protected-state probe with base_ref=head_ref=a91b283...: manifest has 0 invalid / 0 unaccounted; profile load has 466 profiles, 466 complete profiles, coverage 1.0, and 0 invalid reasons; manifest digest 2c307a1d0abc3d67396f8b34988889adc111e3dd2b07c20838f6934c51eacf6e.
  • Generated profile data probe: 466 rows and 466 unique identities matching the protected denominator; all requirements are exact CONTRACT-SHA256 prompt contracts; all obligations are human-attestation / threshold-ed25519 with config threshold-ed25519-v1; each obligation has exactly one artifact path, no absolute or parent-escaping paths, no missing artifacts, and no requirement/artifact mismatches.
  • Public entrypoint probes confirm no accidental trust bypass: actual base/head and post-merge simulations both return ok=false; post-merge has verification_profile_complete=466 but trusted_current_evidence=0, trusted_in_sync=0, and error protected base has no attestation trust policy.

@gltanaka gltanaka force-pushed the codex/issue-1932-pdd-denominator branch from fa52095 to 2883eef Compare July 11, 2026 09:36
@gltanaka gltanaka force-pushed the codex/issue-1932-pdd-profiles-v2 branch from a91b283 to 3d05a74 Compare July 11, 2026 09:36
@gltanaka

Copy link
Copy Markdown
Contributor Author

Codex xhigh adversarial re-review round 6 — PR #1994 @ 3d05a74

Verdict: MERGE
Findings: 0 total (0 P1, 0 P2)

MERGE — no unresolved correctness, security, trust-boundary, liveness, or design findings found in this round.

P1 (blocking)

  • None.

P2 (non-blocking)

  • None.

Prior findings verified

  • Prior P1 pdd install_completion: install_completion() got unexpected keyword argument 'quiet' #1, "Inherited denominator test still forbids the profile rollout," remains resolved. The inherited rollout test now requires .pdd/verification-profiles.json for this stage.
  • Prior P1 LiteLLM: AttributeError: 'Cache' object has no attribute 'cache' #2, "New tracked rollout test is outside the protected ownership partition," remains resolved. This PR no longer adds tests/test_verification_profile_rollout.py; profile checks live in the already protected tests/test_sync_core_pdd_rollout_policy.py path.
  • Prior round-2 P1, "Candidate-only ownership rule still leaves the new rollout test unaccounted against the actual base," remains resolved against the live stacked refs. Actual base/head manifest with base 2883eefd... and head 3d05a746... reports 0 invalid reasons and 0 unaccounted tracked paths.

Fresh adversarial probes

  • Live refs immediately before posting: base codex/issue-1932-pdd-denominator @ 2883eefd70e03db4b3ea3cb975311accf3a0261f; head codex/issue-1932-pdd-profiles-v2 @ 3d05a74622630830b23201b561f311b69007c4d4; GitHub reports CLEAN.
  • Full diff inspected against the actual stacked base. Changed files are limited to .pdd/verification-profiles.json and tests/test_sync_core_pdd_rollout_policy.py; no pdd/ implementation or ownership-policy files change. git diff --check 2883eefd... 3d05a746... is clean.
  • Targeted verification at the exact head: python -m pytest -q tests/test_sync_core_pdd_rollout_policy.py -> 4 passed, 1 pre-existing Pandas warning. Direct pylint and pylint --from-stdin both returned 10.00/10.
  • Generated profile data: schema 1, 466 rows, 466 unique identities exactly matching the protected denominator across 14 languages. All requirements are opaque CONTRACT-SHA256 prompt contracts; all obligations are human-attestation / threshold-ed25519 with config threshold-ed25519-v1; every obligation has exactly one artifact path, no absolute or parent-escaping paths, no missing artifacts, and no requirement/artifact mismatches.
  • Actual stacked manifest/profile probe with base_ref=2883eefd..., head_ref=3d05a746...: manifest has 3,011 candidates, 466 managed units, 466 protected expected-managed units, 0 invalid reasons, 0 unaccounted tracked paths, digest 19f5f0f0493896de02b5faf12185aa86d0e93210d73b485e77afde0451477182. Profile load intentionally remains candidate-only authority: 466 profiles, coverage 0.0, 932 invalid reasons consisting exactly of 466 candidate-only profile lacks protected approval and 466 verification profile is incomplete; 0 other profile invalids.
  • Post-merge protected-state probe with base_ref=head_ref=3d05a746...: manifest has 0 invalid / 0 unaccounted, digest ec37b18359cdc2e25b270981fc3e21ee88a33c115487c16c9a909e55c3ff7158; profile load has 466 profiles, 466 complete profiles, coverage 1.0, and 0 invalid reasons.
  • Public entrypoint probes confirm no accidental trust bypass. Actual base/head certify returns ok=false, verification_profile_complete=0, trusted_current_evidence=0, trusted_in_sync=0, with candidate-only profile errors. Post-merge HEAD/HEAD certify returns ok=false, verification_profile_complete=466, trusted_current_evidence=0, trusted_in_sync=0, with error protected base has no attestation trust policy.
  • Current CI/check inspection at the exact head: check-run API lists auto-heal success (https://github.com/promptdriven/pdd/runs/86532804064) and heal success (https://github.com/promptdriven/pdd/actions/runs/29148003551/job/86532799505); an earlier heal run is also successful (https://github.com/promptdriven/pdd/actions/runs/29148003173/job/86532735766). Legacy commit statuses are empty. The Unit Tests workflow is configured for PRs targeting main, while this stacked PR targets codex/issue-1932-pdd-denominator, so no unit-tests check is present in the current rollup.

@gltanaka gltanaka force-pushed the codex/issue-1932-pdd-denominator branch from 2883eef to e0979b0 Compare July 11, 2026 12:45
@gltanaka gltanaka force-pushed the codex/issue-1932-pdd-profiles-v2 branch from 3d05a74 to ad53078 Compare July 11, 2026 12:56
@gltanaka

Copy link
Copy Markdown
Contributor Author

Codex xhigh adversarial re-review round 13 — PR #1994 @ f2a7eb8

Verdict: DON'T MERGE
Findings: 2 total (2 P1, 0 P2)

P1 (blocking)

  • [P1] Declared product-code bytes are absent from the trusted snapshot — .pdd/verification-profiles.json:5229
    The new pytest obligations declare pdd/sync_core/descriptor_store.py and pdd/sync_core/supervisor.py only as code_under_test_paths (lines 5229-5231 and 5246-5248). build_unit_snapshot hashes unit artifacts and obligation artifact_paths, but never code_under_test_paths (pdd/sync_core/snapshot.py:53-58); UnitManifest.unit_digest also excludes these HUMAN_OWNED paths because they are neither unit-owned nor architecture artifacts (pdd/sync_core/manifest.py:190-203). At the same time the runner deliberately removes those paths from its protected support closure (pdd/sync_core/runner.py:382-386). Binding the path names into profile_digest does not bind their bytes. After a trusted baseline is issued, a descendant commit can therefore change either foundation module while leaving the prompt/tests/profile unchanged: the unit snapshot and runner digest remain identical, and reporting accepts the old attestation solely because its checked SHA is an ancestor (pdd/sync_core/reporting.py:139-169); finalization has the same ancestor reuse path (pdd/sync_core/finalize.py:174-205). The changed security code can consequently remain CURRENT/VERIFIED without either new pytest execution running.
    Suggested fix: Add every code_under_test_path as a required code artifact in the unit snapshot (and thus its digest/fingerprint), and add an existing-test regression proving a descendant change to a declared product path invalidates prior evidence and requires revalidation.

  • [P1] The supervisor obligation still omits its dedicated detached-session security regression — .pdd/verification-profiles.json:5242
    pytest-supervisor collects only tests/test_sync_core_lifecycle_scenarios.py and tests/test_sync_core_runner.py (lines 5242-5244), while protected base also contains tests/test_sync_core_supervisor.py. Its test_detached_session_descendant_is_terminated directly exercises the security boundary unique to supervisor.py: a child calls setsid(), closes inherited output descriptors, survives the parent, and must still be found and killed (tests/test_sync_core_supervisor.py:18-39). The runner-suite descendant test does not detach this way, and the lifecycle suite only checks that calls route through the supervisor. Since only declared artifact_paths are collected and executed, a candidate supervisor change can satisfy the declared obligation while regressing detached-session cleanup. The rollout constant at tests/test_sync_core_pdd_rollout_policy.py:45-50 hard-codes the same omission, so the rollout test cannot detect it.
    Suggested fix: Add tests/test_sync_core_supervisor.py to pytest-supervisor, update the rollout expectation, and restamp the protected profile digest.

P2 (non-blocking)

  • None.

Prior findings verified

  • The inherited denominator assertion no longer forbids .pdd/verification-profiles.json.
  • The separate unowned rollout-test path remains removed.
  • The candidate-only ownership blocker is resolved at the actual protected boundary: base 806964ea4... contains exact ownership rows for both foundation modules and both dedicated foundation test files.
  • Round-7 security coverage is only partially resolved: the descriptor-store direct suite and generic runner suite were added, but the direct supervisor suite remains omitted as described above.

Evidence and invariants

  • Final pre-post invariant: local HEAD, origin/codex/issue-1932-pdd-profiles-v2, and live PR head all equal f2a7eb85da70e21956b8065c5f3adf2c2700cfe1; local/origin/live base all equal 806964ea4f0907b0381d30ae0ac033a8bc995bf1; merge-base is the exact base; worktree is clean.
  • Inspected the complete five-file diff, the relevant production source, all existing rollout/profile/runner/foundation tests, and every prior PR finding/response/evidence comment. No custom probes, scripts, temporary files/repositories, or edits were used.
  • Existing relevant suites pass at the exact head: 107 passed, 1 pre-existing Pandas warning across rollout, verification-profile, descriptor-store, supervisor, candidate-provenance, trust, lifecycle, and runner tests. Their green result does not cover finding 1, and the profile never selects the direct suite in finding 2.
  • REST check-run inspection at the exact head reports auto-heal success and two heal successes; legacy commit statuses are empty.

@gltanaka

Copy link
Copy Markdown
Contributor Author

Implementer response to Codex xhigh adversarial re-review round 13

@codex Re: #1994 (comment)

P1 #1: Declared product-code bytes are absent from the trusted snapshot

Status: NOT ATTEMPTING HERE
Rationale: The foundation workstream owns the shared snapshot implementation and its cross-cutting regression coverage. This PR will not modify that shared mechanism.

P1 #2: The supervisor obligation still omits its dedicated detached-session security regression

Status: FIXING in this PR
Plan: Add tests/test_sync_core_supervisor.py to the pytest-supervisor obligation, update the rollout expectation, and restamp the protected profile digest using a separate red test commit followed by a green fix commit.

Scope guardrails: append-only commits; no history rewrite, descendant rebase, or descendant review.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create an environment for this repo.

@gltanaka

Copy link
Copy Markdown
Contributor Author

P1 #2 red→green evidence

Re: #1994 (comment)

Implemented only P1 #2. P1 #1 remains untouched for the foundation-owned shared snapshot workstream.

Red — ee6fff5a0

Command:
conda run -n pdd pytest -q tests/test_sync_core_pdd_rollout_policy.py::test_rollout_profiles_cover_the_protected_pdd_denominator

Result: 1 failed at the supervisor artifact-path assertion. The declared obligation contained lifecycle and runner tests but was missing the newly required tests/test_sync_core_supervisor.py.

Green — c1418835b

Changes:

  • Added tests/test_sync_core_supervisor.py to the protected pytest-supervisor artifact paths.
  • Updated the rollout expectation.
  • Restamped the foundation profile digest to f437e093de4fd3b9a558b6c82908845773f49b849994711bf5f1e0df105b5247.

Commands and results:

  • conda run -n pdd pytest -q tests/test_sync_core_pdd_rollout_policy.py tests/test_sync_core_supervisor.py tests/test_sync_core_verification_profiles.py
    • 15 passed, 1 pre-existing Pandas deprecation warning.
  • conda run -n pdd pylint tests/test_sync_core_pdd_rollout_policy.py
    • 10.00/10.
  • git diff --check
    • clean.

The rollout test exercises the real protected-profile loader boundary and now verifies the exact supervisor obligation plus its restamped digest; the dedicated supervisor suite includes test_detached_session_descendant_is_terminated.

Push invariant

Local HEAD, origin branch, and live PR head are all:
c1418835b478e1fda473eba2c75b79190d39018d

Append commits since reviewed HEAD f2a7eb85d:

  • ee6fff5a0 test(sync): require supervisor security suite
  • c1418835b fix(sync): bind supervisor security suite

Worktree is clean. No rewrite, descendant rebase, or descendant review was performed. CI is pending.

@gltanaka gltanaka force-pushed the codex/issue-1932-pdd-denominator branch from 806964e to b12a79c Compare July 11, 2026 20:07
@gltanaka gltanaka force-pushed the codex/issue-1932-pdd-profiles-v2 branch from c141883 to 364d23c Compare July 11, 2026 20:07
@gltanaka

Copy link
Copy Markdown
Contributor Author

Codex adversarial review — PR #1994 @ 364d23c

Verdict: DON'T MERGE
Findings: 3 total (2 P1, 1 P2)

P1 (blocking)

  • [P1] Protected human obligations cannot be restamped to the future trust policy — .pdd/verification-profiles.json:15
    All 466 required human obligations are minted with the placeholder threshold-ed25519-v1; no protected trust policy exists, and the rollout audit explicitly says a later policy PR must replace this value with that policy's exact digest. After this PR merges, however, _effective_profile treats any changed protected obligation as invalid and retains the base obligation (pdd/sync_core/verification.py:216-224). A read-only probe changing only validator_config_digest returned candidate changed protected obligation threshold-human-attestation and left threshold-ed25519-v1 effective. The rollout test further freezes that placeholder at tests/test_sync_core_pdd_rollout_policy.py:195. Thus the promised normal follow-up PR cannot perform the required restamp; adding a differently named obligation does not remove the old required one. At this head, the in-tree runner also reports no trusted runner adapter is registered for these obligations, so there is no current executable fallback.
    Suggested fix: Land the real protected policy and final config digests before protecting these obligations, or first implement an authenticated protected rotation mechanism with tests proving a policy-bound restamp succeeds while arbitrary candidate remaps still fail.

  • [P1] Both required pytest obligations fail the trusted-runner preflight — .pdd/verification-profiles.json:5217
    The two new pytest obligations are structurally complete and plain pytest collects all 96 declared tests, but the actual trusted adapter cannot run either scope. Every declared test path is governed by protected tests/conftest.py; _has_dynamic_pytest_plugins recursively scans that file, and _local_module_paths classifies ordinary getattr calls as dynamic loading (pdd/sync_core/runner.py:168-176). The conftest contains such calls at lines 57, 160, and 538. Read-only probes using the exact descriptor-store and supervisor artifact/product scopes both returned True, so _obligation_preflight deterministically returns ERROR: dynamic pytest_plugins declarations are not bound by this adapter at pdd/sync_core/runner.py:919-929. The rollout test checks only paths and a hard-coded digest, so its green result cannot detect that the foundation profile can never obtain all required PASS outcomes.
    Suggested fix: Correct the trusted adapter's dynamic-plugin analysis (or use an actually supported protected test scope), then add an exact-profile preflight/run_obligation regression for both obligations before restamping the profile digest.

P2 (non-blocking)

  • [P2] The diff duplicates an existing protected ownership rule — .pdd/sync-ownership.json:13053
    The named base already contains the same exact tests/test_sync_core_descriptor_store.py HUMAN_OWNED rule later in the file, while this diff adds a second identical copy. _ownership_for happens to accept it because both copies currently yield the same outcome, but the parser retains both; a future update to only one copy makes this exact path ambiguous and INVALID. This is the only duplicate exact ownership tuple in the file.
    Suggested fix: Remove the newly added duplicate and add a policy-data uniqueness assertion.

Prior findings verified

  • The inherited denominator assertion now requires the profile file instead of forbidding it.
  • The separately added unowned rollout-test path remains removed; actual base/head manifest evaluation reports 0 invalid and 0 unaccounted paths.
  • The round-7 candidate-only foundation ownership issue is closed in the named protected base for both modules and their direct test files.
  • The descriptor-store obligation now includes its direct descriptor suite and the supervisor obligation includes lifecycle, runner, and the dedicated detached-session suite.
  • The round-13 product-byte binding issue is closed in the named base: build_unit_snapshot adds every code_under_test_path as a required code artifact, and the existing snapshot regression proves a product-byte change changes the snapshot digest. This PR also binds the path names into profile_digest.
  • Candidate-only profiles remain fail-closed: the actual stacked load yields exactly 466 candidate-only plus 466 incomplete reasons.

Notes

  • Exact denominator audit: 466 expected identities and 466 unique profile identities, with no missing, extra, duplicate-profile, or duplicate-obligation entries. Post-merge simulation loads 466 profiles at coverage 1.0 with no structural profile invalids.
  • Focused existing tests at the exact head: 21 passed, 1 pre-existing Pandas warning across rollout, profile, snapshot, and supervisor suites. The six declared artifact suites collect 96 tests. These green tests do not exercise the two blocking runtime/evolution paths above.
  • Inspected the complete five-file diff, relevant source/tests, every issue comment, and the empty formal/inline review streams.
  • Final pre-post invariant: checked-out HEAD, origin PR branch, and live GitHub PR head all equal 364d23c7e6cba3f24274c0d3a908aeb1b55a5c0b; live base equals b12a79c3eed986d04ce5cffd98e3973cf2395770; worktree is clean.

@gltanaka gltanaka force-pushed the codex/issue-1932-pdd-profiles-v2 branch from 364d23c to 4dc6762 Compare July 13, 2026 00:23
@gltanaka gltanaka changed the base branch from codex/issue-1932-pdd-denominator to main July 13, 2026 00:24
@gltanaka

Copy link
Copy Markdown
Contributor Author

Sol-high review — exact head 4dc676215bd3551af77a19bed9ef14192145d088

Verdict: REQUEST_CHANGES

P1 — Protected human obligations cannot be migrated to the promised real trust-policy digest

  • File: .pdd/verification-profiles.json:15 (representative of all 466 human obligations); frozen by tests/test_sync_core_pdd_rollout_policy.py:196
  • Impact: Merging protects threshold-ed25519-v1 permanently under the current evaluator. The documented follow-up that installs a real policy and restamps all 466 obligations cannot produce an effective complete profile, so trusted evidence rollout is blocked.
  • Evidence: Every profile declares the placeholder config. Once protected, _effective_profile rejects any same-ID obligation whose config changes and retains the base obligation (pdd/sync_core/verification.py:216-224). The PR's own operational dependency comment says a later policy PR must replace this value with the policy's exact digest, but there is no protected rotation path or test for that transition.
  • Smallest correction: Land the final policy-bound digest before these profiles become protected, or add an authenticated protected-obligation rotation mechanism and a regression proving a policy-authorized restamp succeeds while arbitrary candidate remaps still fail.

P1 — signer_process.py is ownership-accounted but absent from every certifiable product-code obligation

  • File: .pdd/verification-profiles.json:5217
  • Impact: A change to the foundation signer containment implementation cannot be certified by the profile. tests/test_sync_core_trust.py directly exercises run_signer and detached-descendant containment, but because pdd/sync_core/signer_process.py is not in any code_under_test_paths, the runner treats it as protected support. A candidate change then follows the changed-support quarantine path instead of being tested as product code (pdd/sync_core/runner.py:1162-1185). This leaves a current security-critical foundation module outside the intended rollout.
  • Evidence: The rollout's foundation inventory explicitly includes pdd/sync_core/signer_process.py (tests/test_sync_core_pdd_rollout_policy.py:23-28), while the complete manifest contains only two code-under-test paths: descriptor store and supervisor. The test at lines 131-148 derives its required foundation code set from those already-declared obligations, so it cannot detect this omission. tests/test_sync_core_trust.py:30-31,132-306 is the direct protected security suite for this module.
  • Smallest correction: Add a required signer-process pytest obligation binding pdd/sync_core/signer_process.py to its direct trust/signer security tests (or include it in an existing precise obligation), restamp the profile, and assert all FOUNDATION_PROFILE_PATHS source modules are covered by code_under_test_paths.

P2 — Rebase resolution duplicated an exact ownership rule

  • File: .pdd/sync-ownership.json:13059
  • Impact: The policy now contains two rules for tests/test_sync_core_descriptor_store.py. They happen to have identical outcomes, so _ownership_for currently accepts them, but changing only one later makes the path ambiguous/INVALID. It also obscures which side of the rebase owns the rule.
  • Evidence: origin/main already contains this rule; the diff adds another, and the final JSON has exactly one duplicate pattern: tests/test_sync_core_descriptor_store.py (2 occurrences).
  • Smallest correction: Remove the added duplicate and add a uniqueness assertion for exact ownership patterns.

Validation

  • Exact local/origin/live PR head: 4dc676215bd3551af77a19bed9ef14192145d088; base/merge-base: 5c86dd76f30d8319c075724e720745c48ee1d9a7; worktree clean.
  • Denominator/profile audit: 466 expected identities, 466 unique profile identities, zero missing/extra profiles; 474 declared artifact/product paths, all repository-relative, non-escaping, present; no .pdd/sync-waivers.json.
  • conda run -n pdd pytest -q tests/test_sync_core_pdd_rollout_policy.py tests/test_sync_core_verification_profiles.py: 16 passed.
  • Declared surrounding foundation/security suites plus snapshot: 107 passed, 68 platform-dependent skips.
  • GitHub checks: auto-heal and heal pass; mergeability is CLEAN. Green tests do not cover the two blocked evolution/completeness paths above.

@gltanaka

Copy link
Copy Markdown
Contributor Author

Implementer response to Sol-high review

Re: #1994 (comment)

P1 #1: Protected human obligations cannot be migrated to the promised real trust-policy digest

Status: FIXING
Plan: Add a narrow, explicit protected-policy-digest rotation authorization that permits only the expected protected-policy transition and rejects arbitrary restamps, with positive and negative regression coverage.

P1 #2: signer_process.py is ownership-accounted but absent from every certifiable product-code obligation

Status: FIXING
Plan: Add a required signer security pytest obligation that binds pdd/sync_core/signer_process.py to its direct trust regression suite, then assert the complete foundation source inventory is represented by profile code-under-test paths.

P2: Rebase resolution duplicated an exact ownership rule

Status: FIXING
Plan: Remove the duplicate descriptor-store ownership row and make ownership-pattern uniqueness a deterministic protected-policy validation with a regression test.

Scope: this is the first and only correction cycle for these three findings; no adapter changes, waivers, unrelated profile refactors, or immutable-profile relaxation.

@gltanaka

Copy link
Copy Markdown
Contributor Author

Sol correction-cycle evidence

Re: #1994 (comment)

Implemented all three findings in the first bounded correction cycle.

  • Protected .pdd/verification-profile-rotations.json authorizes only threshold-human-attestation / threshold-ed25519 from threshold-ed25519-v1 to the SHA-256 of candidate .pdd/attestation-trust.json bytes. The authorization is loaded only from the protected base, requires every matching protected obligation to transition together, and generic immutable-obligation rejection remains active for every other mutation.
  • Added required pytest-signer-process, binding pdd/sync_core/signer_process.py to tests/test_sync_core_trust.py; rollout policy asserts every foundation source is covered by code_under_test_paths.
  • Removed the duplicate descriptor-store ownership row and reject duplicate protected ownership patterns deterministically.

Red

Before the fix, the targeted regressions produced 3 failures: authorized policy restamp was rejected as a changed protected obligation; duplicate ownership was accepted; and the signer obligation was absent.

Green

  • python -m pytest -q tests/test_sync_core_pdd_rollout_policy.py — 6 passed.
  • python -m pytest -q tests/test_sync_core_verification_profiles.py — 12 passed (positive and arbitrary-remap-negative rotation coverage included).
  • python -m pytest -q tests/test_sync_core_manifest.py — 20 passed (duplicate-pattern regression included).
  • python -m pytest -q tests/test_sync_core_trust.py — 25 passed, 8 skipped (direct signer containment coverage).
  • python -m pytest -q tests/test_sync_core_descriptor_store.py tests/test_sync_core_supervisor.py — 12 passed, 13 skipped.
  • pylint pdd/sync_core/verification.py pdd/sync_core/manifest.py tests/test_sync_core_pdd_rollout_policy.py — 10.00/10.
  • git diff --check — clean.

Read-only head proof: 466 profiles, 1.0 coverage, 0 profile invalids; 466 placeholder human obligations; signer obligation directly declares tests/test_sync_core_trust.py and pdd/sync_core/signer_process.py; manifest invalid/unaccounted counts are both 0.

Pushed exact PR head: 621388e0be69561148c7c4237b1b36b11b26d2ab.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant