Skip to content

Feature Spec: PJSIP Artifact Validation Workflow #20

Description

@alemar11

Feature Spec: PJSIP Artifact Validation Workflow

Source

  • 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.
  • Validate IPA packages, code signing, dynamic frameworks, or nonexistent XCFramework dSYMs.
  • 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.

Product / Repository Scope

  • Affected repositories: alemar11/pjsip-builder.
  • Allowed paths: .gitignore, .agents/skills/pjsip-builder-validation/**, AGENTS.md, README.md, build.py, validate_artifacts.py, test_apple_tls_backend.py, tests/**.
  • Spec target branch: codex/pjsip-artifact-validation.

Feature Dependencies

upstream_feature_spec_ref dependency_reason

Acceptance Criteria

  • 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions