Skip to content

Validate immutable portable tool records - #91

Open
omry wants to merge 1 commit into
pr90from
pr91
Open

Validate immutable portable tool records#91
omry wants to merge 1 commit into
pr90from
pr91

Conversation

@omry

@omry omry commented Aug 17, 2026

Copy link
Copy Markdown
Owner

Add record-local validation for every v1 record family: tool version policy and aliases, release manifests and contracts, target identities and records, binding contracts and artifacts, payloads, artifact sources, native package sets, integration fixtures, and validation profiles. Version policy follows each record's declared scheme, artifacts require exact size and digest, and every diagnostic has focused negative coverage.

Wire record-local validation into record decoding, which PTD-03 deliberately left unhooked.

Scope authority

Task: PTD-04 — Validate Immutable Portable Tool Records, defined in docs/PORTABLE_TOOL_DEFINITION_IMPLEMENTATION_PLAN.md (PR #86 in this stack), under the normative Portable Tool Definition Design.

Acceptance criteria:

  • each kind validates without graph traversal;
  • version policy uses the declared scheme;
  • artifacts require exact size and digest;
  • diagnostics have focused negative tests;
  • go.mod promotes the shared version dependency and stays stable under go mod tidy.

Included from the retired PR 85

The release-alias correction moves here as the plan directs: release aliases must be a bounded array of canonical, unique, sorted values, each different from the exact version.

Boundary note

Typed parameter schemas and target parameter constraints are validated here rather than in PTD-05, because record-local validation reaches them directly. PTD-05 owns the cross-record part — narrowing a target against its contract, and fixture coverage over support tuples.

Exclusions: target coverage, reachability, source-mapping completeness, resolution. Sources: parked extraction sources b39985d247e5 and 37ca781bd6cb (alias correction).

@omry
omry changed the base branch from main to pr90 August 17, 2026 16:28
@omry
omry force-pushed the pr91 branch 5 times, most recently from 637c09a to ae01823 Compare August 17, 2026 21:33
@omry
omry force-pushed the pr91 branch 2 times, most recently from 50be9b8 to ab7be22 Compare August 18, 2026 05:35
@omry
omry force-pushed the pr91 branch 3 times, most recently from 4317e9c to 14aead6 Compare August 18, 2026 06:01
@omry
omry force-pushed the pr91 branch 2 times, most recently from 22bef58 to a06b11a Compare August 18, 2026 06:12
@omry
omry force-pushed the pr91 branch 2 times, most recently from c7b6caf to fb90459 Compare August 18, 2026 11:42

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cb9c1557e1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/toolcatalog/records_validate.go
@omry

omry commented Aug 18, 2026

Copy link
Copy Markdown
Owner Author

@codex, regular review cb9c155

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cb9c1557e1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/toolcatalog/records_validate.go Outdated
Comment thread internal/toolcatalog/records_validate.go
@omry

omry commented Aug 18, 2026

Copy link
Copy Markdown
Owner Author

@codex, regular review 7321362

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 73213620b7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/toolcatalog/records_validate.go Outdated
Comment thread internal/toolcatalog/records_validate.go
@omry

omry commented Aug 18, 2026

Copy link
Copy Markdown
Owner Author

@codex, regular review 9295d22

@omry

omry commented Aug 18, 2026

Copy link
Copy Markdown
Owner Author

PR-cycle state — maintained automatically. Do not edit.

{
  "approval": {
    "approved_revision_fingerprint": "sha256:d417c452aff7285e2e65cb79636c5020534a60129ed339aadfe64c9f583cd9e0",
    "evidence": {
      "delivery_deferral_ledger_digest": "sha256:976f5044b9d7a599e47382e009c5a2d15aa082076d9e2ec40d77891a1d05f343",
      "required_checks": [
        [
          "Linux CI checks",
          "success"
        ],
        [
          "Target smoke (darwin-amd64)",
          "success"
        ],
        [
          "Target smoke (darwin-arm64)",
          "success"
        ],
        [
          "Target smoke (linux-amd64)",
          "success"
        ],
        [
          "Target smoke (linux-arm64)",
          "success"
        ],
        [
          "Windows host smoke (windows-amd64)",
          "success"
        ],
        [
          "Windows host smoke (windows-arm64)",
          "success"
        ]
      ],
      "review_request": {
        "body_digest": "sha256:24d760189c9511210060806295d887fb52ab9f9f93dbd07bbe0212f797327e8e",
        "id": 5329949612
      },
      "review_result": {
        "body_digest": "sha256:488551b51f5876ce6c180dee5a454dfbb79b13c2ad70fa6a178e7b5443c37b53",
        "id": 5330025592
      },
      "revision_fingerprint": "sha256:d417c452aff7285e2e65cb79636c5020534a60129ed339aadfe64c9f583cd9e0",
      "thread_dispositions": {
        "resolved": 13,
        "total": 13
      }
    },
    "evidence_fingerprint": "sha256:5a3e3d91b568803607c1fff206e5834bad0abb3e098918168ac294ebe9d1904c",
    "rounds": 8
  },
  "checks": {
    "conclusion": "success",
    "count": 7
  },
  "class_sweep": {
    "action": "audited every cross-record reference in records_validate.go; all ten prefix-only checks had the defect and now mirror their owning validator",
    "removed": "validateReferenceUnderV1, which no caller retained",
    "self_caught": "validateFixtureReferenceV1 first used validRecordSegmentV1, looser than the validRecordIdentifierV1 the fixture record applies to its own name",
    "sites": [
      "release target",
      "release validation profile",
      "target validation profile",
      "target integration fixture",
      "target package set",
      "target binding package set",
      "target selection package set",
      "target payload",
      "target selection payload",
      "target binding artifact"
    ],
    "tests": "14 negative tests, each verified to fail without its fix",
    "trigger": "five of the first nine findings were the same defect: a cross-record reference validated by namespace prefix rather than by the ID shape its owning record enforces"
  },
  "delivery_deferral_ledger_digest": "sha256:976f5044b9d7a599e47382e009c5a2d15aa082076d9e2ec40d77891a1d05f343",
  "delivery_deferrals": [
    {
      "classification": "design-level; non-actionable in this slice",
      "evidence": "docs/PORTABLE_TOOL_DEFINITION_DESIGN.md:309 defines a binding artifact as owning one exact platform-specific ecosystem artifact, and :319 states the separation exists because the artifact differs by architecture; the only advertised binding ships playwright-1.61.0-py3-none-manylinux1_x86_64.whl, whose py3-none tag covers supported_python 3.10 through 3.14",
      "id": "distinct-ids-for-same-platform-binding-artifacts",
      "owed": "if a future binding requires ABI-specific wheels on one platform, update the design's binding-artifact section first; the ID grammar and validateBindingArtifactIDV1 follow from that",
      "raised": "PR 91 round 2 (review 4961958447, comment 3804818376)",
      "severity": "P2",
      "statement": "binding artifact IDs are platform-keyed, so one binding cannot own two ABI-specific wheels on the same platform",
      "why_deferred": "adding an ID discriminator changes a public schema concept the normative design defines, which this slice's fix authority excludes without explicit approval"
    },
    {
      "classification": "owned by PTD-05, not PTD-04",
      "id": "binding-contract-package-must-be-among-its-requirement-roots",
      "owed": "PTD-05 decides whether the record-local form replaces or supplements the per-artifact form, and records its design basis or drops it deliberately",
      "raised": "PTD-04 proactive audit after round 7, not raised by review",
      "severity": "P2",
      "statement": "BindingContractV1 validates Package and parses every requirement into a distribution, but never checks Package is among them, so a record-locally unsatisfiable contract passes",
      "why_deferred": "the parked validateBindingArtifactAgainstContractV1 already enforces this per-artifact and that hunk is owned by PTD-05; a record-local copy here would multiply-own the invariant, which the Slice Ownership Rule forbids"
    }
  ],
  "findings": [
    {
      "disposition": "fixed in cb9c1557e1c1",
      "id": "reject-contract-references-outside-the-artifact-binding",
      "location": "internal/toolcatalog/records_validate.go:382",
      "round": 1,
      "severity": "P2"
    },
    {
      "disposition": "fixed in cb9c1557e1c1",
      "id": "reject-wheel-filenames-that-disagree-with-artifact-metadata",
      "location": "internal/toolcatalog/records_validate.go:388",
      "round": 1,
      "severity": "P2"
    },
    {
      "disposition": "non-actionable in this slice; recorded as a delivery deferral against the design",
      "id": "allow-distinct-ids-for-same-platform-binding-artifacts",
      "location": "internal/toolcatalog/records_validate.go:1125",
      "round": 2,
      "severity": "P2"
    },
    {
      "disposition": "fixed in 73213620b760; a prefix-only namespace check accepted any in-release ID, including contract IDs that own no size or digest",
      "id": "restrict-source-mappings-to-artifact-record-namespaces",
      "location": "internal/toolcatalog/records_validate.go:124",
      "round": 3,
      "severity": "P2"
    },
    {
      "disposition": "fixed in 73213620b760; fixture selections skipped the validRecordIdentifierV1 check applied to declared selection options",
      "id": "reject-noncanonical-fixture-selection-names",
      "location": "internal/toolcatalog/records_validate.go:563",
      "round": 3,
      "severity": "P2"
    },
    {
      "disposition": "fixed in 9295d22287ae; the round 3 fix still admitted IDs no owning record could hold, so the check now mirrors validatePayloadIDV1 and validateBindingArtifactIDV1 exactly",
      "id": "validate-the-complete-artifact-source-target-id",
      "location": "internal/toolcatalog/records_validate.go:609",
      "round": 4,
      "severity": "P2"
    },
    {
      "disposition": "fixed in 9295d22287ae; PEP 513 and PEP 571 define manylinux1 and manylinux2010 for x86_64 and i686 only, aarch64 arrives with manylinux2014 in PEP 599",
      "id": "reject-legacy-manylinux-tags-on-arm64",
      "location": "internal/toolcatalog/records_validate.go:1277",
      "round": 4,
      "severity": "P2"
    },
    {
      "disposition": "fixed in 015fa1b01036; the symmetric case of the round 4 artifact-side fix, which I tightened without tightening mapping.Source at the same time",
      "id": "reject-malformed-source-record-reference-ids",
      "location": "internal/toolcatalog/records_validate.go:128",
      "round": 5,
      "severity": "P2"
    },
    {
      "disposition": "fixed in 015fa1b01036; the 1024-entry bound moved into validateSortedUniqueStringsV1 so every sorted string collection carries it, and four now-unreachable explicit caps were removed",
      "id": "enforce-the-reference-cap-on-sorted-string-collections",
      "location": "internal/toolcatalog/records_validate.go:324",
      "round": 5,
      "severity": "P2"
    },
    {
      "disposition": "fixed in 907b7245dc58; the tool record is the only record that knows VersionScheme and never applied it to its release references",
      "id": "validate-release-coordinates-under-the-declared-version-scheme",
      "location": "internal/toolcatalog/records_validate.go:56",
      "round": 6,
      "severity": "P2"
    },
    {
      "disposition": "fixed in 907b7245dc58; the revision segment now uses the manifest's own positive canonical-decimal rule",
      "id": "require-canonical-revisions-in-tool-release-references",
      "location": "internal/toolcatalog/records_validate.go:55",
      "round": 6,
      "severity": "P2"
    },
    {
      "disposition": "already fixed in 907b7245dc58 before the review arrived, by the class sweep below",
      "id": "restrict-release-profile-references-to-valid-profile-ids",
      "location": "internal/toolcatalog/records_validate.go:95",
      "round": 6,
      "severity": "P2"
    },
    {
      "disposition": "fixed in 9c8b1def483a; design :193 requires an opaque default_version to name one advertised eligible release and :910 lists an unadvertised default among the static validation failures. Eligibility beyond advertisement stays a graph concern.",
      "id": "require-opaque-defaults-to-identify-an-advertised-release",
      "location": "internal/toolcatalog/records_validate.go:35",
      "round": 7,
      "severity": "P2"
    }
  ],
  "preflight_audit": "before the first review, every field added to the record model in PTD-02 was diffed against its design rule; seven had no validation and were given one in this slice, together with contract-namespace enforcement and wheel-filename agreement",
  "pull_request": {
    "base": {
      "ref": "pr90",
      "sha": "42c6f5fa01b9"
    },
    "head": {
      "ref": "pr91",
      "sha": "9c8b1def483a"
    },
    "number": 91,
    "repository": "github.com/omry/reploy"
  },
  "record_note": "created at round 5 rather than at cycle start: the run's stage marking drifted after the saved swe:pr-cycle definition changed mid-run. Rounds 1 through 4 are reconstructed from PR review, comment, and commit evidence, not from contemporaneous marking. Rounds 5 onward are marked as they happen.",
  "review": {
    "request": "@codex, regular review 9c8b1def483ad973a54296f0850e4df872735857",
    "result": "Codex Review - no issues on 9c8b1def48"
  },
  "revision_fingerprint": "sha256:d417c452aff7285e2e65cb79636c5020534a60129ed339aadfe64c9f583cd9e0",
  "rounds": [
    {
      "attempt": 1,
      "findings": 2,
      "resulting_head": "cb9c1557e1c1",
      "reviewed_head": "9e143b6fb463"
    },
    {
      "attempt": 2,
      "findings": 1,
      "note": "finding deferred, not fixed, so the head is unchanged",
      "resulting_head": "cb9c1557e1c1",
      "reviewed_head": "cb9c1557e1c1"
    },
    {
      "attempt": 3,
      "findings": 2,
      "resulting_head": "73213620b760",
      "reviewed_head": "cb9c1557e1c1"
    },
    {
      "attempt": 4,
      "findings": 2,
      "resulting_head": "9295d22287ae",
      "reviewed_head": "73213620b760"
    },
    {
      "attempt": 5,
      "findings": 2,
      "resulting_head": "015fa1b01036",
      "reviewed_head": "9295d22287ae"
    },
    {
      "attempt": 6,
      "findings": 3,
      "note": "one of the three was already fixed by the class sweep in this same head",
      "resulting_head": "907b7245dc58",
      "reviewed_head": "015fa1b01036"
    },
    {
      "attempt": 7,
      "findings": 1,
      "resulting_head": "9c8b1def483a",
      "reviewed_head": "907b7245dc58"
    },
    {
      "attempt": 8,
      "findings": 0,
      "note": "clean - Codex reported no major issues",
      "resulting_head": "9c8b1def483a",
      "reviewed_head": "9c8b1def483a"
    }
  ],
  "scope_authority": {
    "docs/PORTABLE_TOOL_DEFINITION_DESIGN.md": "sha256:4c8fa535721baf22f67486a46b0b4a04eb7054713d0a892e2d6f9667bba914b6",
    "docs/PORTABLE_TOOL_DEFINITION_IMPLEMENTATION_PLAN.md": "sha256:971113afcedea93da5df3fab42433a1e5f9fea62554f02a3f630e306b9455f00"
  },
  "version": 5
}

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9295d22287

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/toolcatalog/records_validate.go Outdated
Comment thread internal/toolcatalog/records_validate.go
@omry

omry commented Aug 18, 2026

Copy link
Copy Markdown
Owner Author

@codex, regular review 015fa1b

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 015fa1b010

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/toolcatalog/records_validate.go
Comment thread internal/toolcatalog/records_validate.go
Comment thread internal/toolcatalog/records_validate.go Outdated
@omry

omry commented Aug 18, 2026

Copy link
Copy Markdown
Owner Author

@codex, regular review 907b724

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 907b7245dc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/toolcatalog/records_validate.go
Add record-local validation for every v1 record family: tool version policy and aliases, release manifests and contracts, target identities and records, binding contracts and artifacts, payloads, artifact sources, native package sets, integration fixtures, and validation profiles. Version policy follows each record's declared scheme, artifacts require exact size and digest, and every diagnostic has focused negative coverage.

Wire record-local validation into record decoding, which the decoding slice deliberately left unhooked.

Move PR 85's release-alias correction here: release aliases must be a bounded array of canonical, unique, sorted values, each different from the exact version.

Promote the shared version dependency to direct in go.mod, because this is the first slice to import go-version/pkg/semver directly.

Delivers PTD-04 of docs/PORTABLE_TOOL_DEFINITION_IMPLEMENTATION_PLAN.md.
@omry

omry commented Aug 18, 2026

Copy link
Copy Markdown
Owner Author

@codex, regular review 9c8b1de

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Delightful!

Reviewed commit: 9c8b1def48

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

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

Labels

approved PR reviewed and approved

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant