You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
User conversation selecting a repository-scoped Codex skill backed by one deterministic XCFramework/static-archive validator.
build.py
AGENTS.md
.gitignore
test_apple_tls_backend.py
alemar11/pjsip-builder#11
alemar11/pjsip-builder#12
alemar11/pjsip-builder#13
alemar11/pjsip-builder#14
Recent debug and release XCFramework validation evidence from the PJSIP Xcode-debug and Apple-TLS tasks.
Planning Identity
Feature slug: pjsip-artifact-validation.
Planning scope: PJSIP Builder artifact verification and agent workflow.
Delivery type: github-pr.
Problem
PJSIP Builder creates a static XCFramework from platform and architecture archives, but its reusable contract ends when xcodebuild -create-xcframework succeeds. Maintainers and agents currently reconstruct plutil, lipo, otool, ar, and nm probes during individual tasks. That repetition is inconsistent, is not directly reusable by CI or humans, and can miss mismatches between XCFramework metadata, archive architectures, Mach-O platforms, deployment targets, headers, symbols, and selected optional codecs.
A repository skill alone would improve agent guidance but would leave project correctness dependent on an AI workflow. A standalone validator alone would provide deterministic evidence but would not teach agents when a quick check is sufficient, when a destination must be rebuilt, or when the full matrix is justified.
Goals
Add one deterministic, human- and CI-usable artifact-validation command as the authoritative correctness implementation.
Make successful build.py completion include fast validation of the XCFramework it just produced against the selected destinations and feature options.
Add a repository-scoped Codex skill that selects an appropriate validation tier and delegates pass/fail judgment to the authoritative command.
Replace the broad ignore rule that hides normal nested source, test, and skill paths while preserving ignores for generated build, source, download, cache, log, and Xcode-project output.
Document the validation contract and agent expectations in the root README and AGENTS.md.
Non-Goals
Make the skill or its hidden directory the only entry point to artifact validation.
Duplicate the validation implementation inside the skill or rely on improvised shell pipelines for the normal pass/fail decision.
Fix dependency-cache identity or interrupted-cache publication tracked by alemar11/pjsip-builder#11.
Declare or repair transitive consumer linker metadata tracked by alemar11/pjsip-builder#12; this feature may compile headers/modules but does not claim that the static XCFramework is self-linking.
Pin upstream inputs or publish provenance tracked by alemar11/pjsip-builder#13.
Redesign selected-plan preflight validation tracked by alemar11/pjsip-builder#14.
Run a clean all-destination debug/release build after every source edit.
Package or distribute the repository skill as a plugin.
Users And Use Cases
A maintainer can run one command against an existing debug or release XCFramework and receive an actionable human summary or stable machine-readable result.
build.py can fail immediately when the produced XCFramework contradicts the selected build plan.
A Codex agent changing architecture flags, packaging, codecs, headers, or TLS behavior can choose a quick, affected-destination, or full validation tier without inventing a new command sequence.
CI can invoke the same validator used locally without loading the Codex skill.
Requirements
Add a top-level validate_artifacts.py as the single authoritative validation implementation. It accepts an XCFramework path plus explicit expected configuration, selected destinations, deployment targets, and optional-codec expectations; it must also be callable from build.py without duplicating validation rules.
Parse the XCFramework Info.plist and require every selected destination to have exactly one expected library entry, binary, header directory, platform variant, and architecture set. A subset build validates only its selected destinations; a normal all-destination build requires the complete macOS, iOS-device, iOS-Simulator, and Mac-Catalyst matrix.
Compare each plist architecture declaration with lipo results. For every declared architecture, inspect all archive members' Mach-O build metadata with otool and reject mixed or incorrect platform IDs, architectures, or minimum deployment targets, including optional-codec objects merged into libpjproject.a.
Thin universal archives into an automatically cleaned temporary directory before archive-member inspection with ar. Reject empty, malformed, or architecture-inconsistent archives and retain the original artifact untouched.
Verify the expected umbrella header and modulemap, per-slice PJ_OS_NAME and PJ_M_NAME overrides, representative required PJSIP definitions such as pjsua_create, optional Opus/G.729 headers and defined symbols when enabled, and their absence when disabled. Forbidden stale dependency headers or defined symbols must produce a failure without using broad patterns that reject PJSIP's own TLS APIs.
Resolve Apple developer tools through the selected Xcode environment, preferring xcrun --find where appropriate, and return actionable missing-tool or malformed-output diagnostics. ipatool is never part of this workflow; direct vtool inspection of static archives is not a required path.
Provide concise human output and a stable JSON result containing artifact identity, checked slices and architectures, validation findings, and final status. Any failed invariant returns nonzero; warnings cannot silently downgrade a required check.
Invoke the fast validator from build.py after modulemap, umbrella-header, and slice-header generation. Pass the normalized selected destinations, configuration, deployment targets, and optional-codec state directly from the resolved build invocation. A validation failure makes the build command fail while preserving the artifact and diagnostic evidence for inspection.
Replace .gitignore's broad nested-path exclusion with targeted rules that continue ignoring current generated directories, caches, logs, .DS_Store, and generated .xcodeproj bundles while allowing .agents/skills/** and conventional tests/** content to be tracked. Preserve existing tracked source and documentation behavior.
Add .agents/skills/pjsip-builder-validation/SKILL.md. Its description must activate only for PJSIP Builder XCFramework/archive validation and relevant build-packaging changes. The workflow inspects requested scope and current changes, selects quick, affected-destination, or full validation, invokes validate_artifacts.py as the pass/fail authority, and uses raw tools only for focused diagnosis after a failure.
The skill must not start a long or destructive rebuild merely because an existing artifact can be checked. It must distinguish validation of an existing artifact from rebuilding one, avoid reading an artifact while another build is mutating the same path, report the exact tier and evidence used, and stop on an authoritative validator failure.
Update AGENTS.md with the canonical validator command, tier-selection expectations, required post-change checks, and the boundary with adjacent issues. Update the root README with the human-facing command and JSON usage. Skill-specific procedure remains in SKILL.md, not duplicated wholesale in AGENTS.md.
Add deterministic unit coverage for matrix derivation, plist/archive/tool-output parsing, wrong-platform and mixed-member rejection, optional-codec presence/absence, missing headers/modules/symbols, malformed tools, JSON output, and build.py postcondition propagation. Tests use fixtures or mocked subprocess results and do not require a full build.
One top-level validator can verify an existing PJSIP XCFramework independently of Codex and returns stable human and JSON results with nonzero failure semantics.
XCFramework plist entries, actual lipo architectures, every archive member's platform/minimum-target metadata, archive integrity, required headers/modules/macros, and representative symbols are checked against the explicit selected build plan.
Optional Opus and G.729 expectations are validated in both enabled and disabled states, and stale forbidden dependency content fails without false positives on PJSIP-owned TLS APIs.
build.py runs the authoritative fast validation after final package customization and fails the build command when the produced artifact violates the selected destination, deployment-target, configuration, or codec contract.
Repository ignore rules permit committed .agents/skills/** and tests/** content while all existing generated build/source/download/cache/log/Xcode-project paths remain ignored.
The repository skill selects and reports quick, affected-destination, or full validation, invokes the validator for normal judgment, avoids unnecessary rebuilds, and reserves raw Apple tools for diagnosis.
AGENTS.md and the root README identify the canonical command, agent validation policy, JSON interface, and the non-overlap with cache, provenance, preflight, and transitive-link-dependency work.
Unit tests cover successful and failing structural cases without requiring real builds, and one real all-destination debug artifact plus one real all-destination release artifact pass the validator at the final implementation HEAD.
One targeted debug build with Opus and G.729 enabled demonstrates that merged optional-codec members retain the selected destination's platform and deployment metadata and satisfy enabled-feature header/symbol expectations.
Validation Expectations
Run Python compilation and the complete repository unit-test suite, including existing Apple-TLS regression coverage and the new validator fixtures.
Run the validator in human and JSON modes against the final debug and release all-destination XCFrameworks.
Run one targeted debug build with both optional codecs enabled, then validate its selected destination and feature expectations.
Exercise at least one deliberately corrupted or mocked wrong-platform case and prove the validator returns nonzero with an actionable finding.
Exercise the repository skill through representative direct, implicit, incomplete-artifact, and unrelated requests to verify activation boundaries and tier selection.
Full real builds are constrained validation: perform one debug matrix, one release matrix, and one targeted optional-codec build. Retry an individual build at most once only for a demonstrated transient toolchain or network failure after retaining the first log. A reproducible build or validator failure blocks completion; fixture-only success is not an allowed fallback for the required real artifacts.
Run git diff --check and inspect ignored/tracked paths before publication so generated trees remain excluded and both skill and test paths are tracked.
Risks
Apple tool output can change across Xcode releases. Keep parsers narrow, fixture-tested, and fail with captured context rather than guessing.
Scanning every member of merged static archives costs more than checking one object. Keep the fast path bounded to existing artifacts and reserve rebuilds for the selected skill tier.
Incorrect symbol allow/deny patterns can create false confidence or reject valid PJSIP TLS symbols. Use representative defined symbols and explicit stale-dependency evidence.
Replacing the broad ignore rule may expose previously hidden generated paths. Verify git status --ignored against the current repository layout before finalizing it.
Automatic post-build validation tightens success semantics and may reveal existing artifact defects. Treat those as real failures; do not weaken the validator merely to preserve a green build.
Open Questions
None.
Issue-Splitting Notes
First deliver the deterministic validator, its unit coverage, targeted ignore-rule repair, and build.py postcondition integration as one independently useful human/CI slice.
Then deliver the repository skill and concise README/AGENTS.md guidance against the stable validator interface. Do not duplicate validator logic in the skill.
Consumer self-linking and dependency declaration remain under alemar11/pjsip-builder#12; this feature stops at structural/module compilation and explicit artifact-contract validation.
This is planning-time guidance. Implementers may choose a simpler or safer internal design without changing the accepted outcome, scope, constraints, or acceptance criteria.
Feature Spec: PJSIP Artifact Validation Workflow
Source
build.pyAGENTS.md.gitignoretest_apple_tls_backend.pyalemar11/pjsip-builder#11alemar11/pjsip-builder#12alemar11/pjsip-builder#13alemar11/pjsip-builder#14Planning Identity
pjsip-artifact-validation.github-pr.Problem
PJSIP Builder creates a static XCFramework from platform and architecture archives, but its reusable contract ends when
xcodebuild -create-xcframeworksucceeds. Maintainers and agents currently reconstructplutil,lipo,otool,ar, andnmprobes during individual tasks. That repetition is inconsistent, is not directly reusable by CI or humans, and can miss mismatches between XCFramework metadata, archive architectures, Mach-O platforms, deployment targets, headers, symbols, and selected optional codecs.A repository skill alone would improve agent guidance but would leave project correctness dependent on an AI workflow. A standalone validator alone would provide deterministic evidence but would not teach agents when a quick check is sufficient, when a destination must be rebuilt, or when the full matrix is justified.
Goals
build.pycompletion include fast validation of the XCFramework it just produced against the selected destinations and feature options.AGENTS.md.Non-Goals
alemar11/pjsip-builder#11.alemar11/pjsip-builder#12; this feature may compile headers/modules but does not claim that the static XCFramework is self-linking.alemar11/pjsip-builder#13.alemar11/pjsip-builder#14.Users And Use Cases
build.pycan fail immediately when the produced XCFramework contradicts the selected build plan.Requirements
validate_artifacts.pyas the single authoritative validation implementation. It accepts an XCFramework path plus explicit expected configuration, selected destinations, deployment targets, and optional-codec expectations; it must also be callable frombuild.pywithout duplicating validation rules.Info.plistand require every selected destination to have exactly one expected library entry, binary, header directory, platform variant, and architecture set. A subset build validates only its selected destinations; a normal all-destination build requires the complete macOS, iOS-device, iOS-Simulator, and Mac-Catalyst matrix.liporesults. For every declared architecture, inspect all archive members' Mach-O build metadata withotooland reject mixed or incorrect platform IDs, architectures, or minimum deployment targets, including optional-codec objects merged intolibpjproject.a.ar. Reject empty, malformed, or architecture-inconsistent archives and retain the original artifact untouched.PJ_OS_NAMEandPJ_M_NAMEoverrides, representative required PJSIP definitions such aspjsua_create, optional Opus/G.729 headers and defined symbols when enabled, and their absence when disabled. Forbidden stale dependency headers or defined symbols must produce a failure without using broad patterns that reject PJSIP's own TLS APIs.xcrun --findwhere appropriate, and return actionable missing-tool or malformed-output diagnostics.ipatoolis never part of this workflow; directvtoolinspection of static archives is not a required path.build.pyafter modulemap, umbrella-header, and slice-header generation. Pass the normalized selected destinations, configuration, deployment targets, and optional-codec state directly from the resolved build invocation. A validation failure makes the build command fail while preserving the artifact and diagnostic evidence for inspection..gitignore's broad nested-path exclusion with targeted rules that continue ignoring current generated directories, caches, logs,.DS_Store, and generated.xcodeprojbundles while allowing.agents/skills/**and conventionaltests/**content to be tracked. Preserve existing tracked source and documentation behavior..agents/skills/pjsip-builder-validation/SKILL.md. Its description must activate only for PJSIP Builder XCFramework/archive validation and relevant build-packaging changes. The workflow inspects requested scope and current changes, selects quick, affected-destination, or full validation, invokesvalidate_artifacts.pyas the pass/fail authority, and uses raw tools only for focused diagnosis after a failure.AGENTS.mdwith the canonical validator command, tier-selection expectations, required post-change checks, and the boundary with adjacent issues. Update the root README with the human-facing command and JSON usage. Skill-specific procedure remains inSKILL.md, not duplicated wholesale inAGENTS.md.build.pypostcondition propagation. Tests use fixtures or mocked subprocess results and do not require a full build.Product / Repository Scope
alemar11/pjsip-builder..gitignore,.agents/skills/pjsip-builder-validation/**,AGENTS.md,README.md,build.py,validate_artifacts.py,test_apple_tls_backend.py,tests/**.codex/pjsip-artifact-validation.Feature Dependencies
Acceptance Criteria
build.pyruns the authoritative fast validation after final package customization and fails the build command when the produced artifact violates the selected destination, deployment-target, configuration, or codec contract..agents/skills/**andtests/**content while all existing generated build/source/download/cache/log/Xcode-project paths remain ignored.AGENTS.mdand the root README identify the canonical command, agent validation policy, JSON interface, and the non-overlap with cache, provenance, preflight, and transitive-link-dependency work.Validation Expectations
git diff --checkand inspect ignored/tracked paths before publication so generated trees remain excluded and both skill and test paths are tracked.Risks
git status --ignoredagainst the current repository layout before finalizing it.Open Questions
Issue-Splitting Notes
build.pypostcondition integration as one independently useful human/CI slice.AGENTS.mdguidance against the stable validator interface. Do not duplicate validator logic in the skill.alemar11/pjsip-builder#12; this feature stops at structural/module compilation and explicit artifact-contract validation.