Skip to content

Land the portfolio generation publisher - #248

Merged
saagpatel merged 2 commits into
mainfrom
pr/portfolio-generation-publisher
Sep 2, 2026
Merged

Land the portfolio generation publisher#248
saagpatel merged 2 commits into
mainfrom
pr/portfolio-generation-publisher

Conversation

@saagpatel

Copy link
Copy Markdown
Owner

What

Lands the portfolio generation publisher that the deployed consumers already expect.

personal-ops (deployed 2026-08-29) reads portfolio truth from ~/.local/state/portfolio-generations whenever a pointer exists there, and notion-operating-system main does the same. The publisher that writes those generations, portfolio_generation.py, existed only on a Codex branch in a work directory that never reached GitHub; the one generation on disk was published by hand from a dirty tree on 2026-08-30 and has been stale since. That staleness is why the nightly notion snapshot readback has failed since 2026-08-26.

This PR is that branch (codex/p11-i009-generation-contract-20260825, pushed as-is for durability) merged with main. No conflicts.

Contents

  • src/github_repo_auditor/portfolio_generation.py: publish, verify and swap-current-previous for coherent, hash-bound portfolio generations under a pointer + releases layout.
  • tests/test_portfolio_generation.py: 277 lines of contract coverage.

Verification

  • uv run pytest: 3660 passed, 2 skipped
  • uv run ruff check src tests: clean

Pairs with

operator-scripts PR that wires publish and verify into the nightly com.d.portfolio-maintenance run. Until both land and a new operator-scripts release is activated, the generation on disk stays stale.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 2, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-02T06:12:06.942018Z 59f3bc8 PR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@saagpatel
saagpatel merged commit 9e2bb60 into main Sep 2, 2026
4 checks passed
@saagpatel
saagpatel deleted the pr/portfolio-generation-publisher branch September 2, 2026 06:10

@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: 59f3bc8f3a

ℹ️ 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 on lines +371 to +372
if not artifacts:
raise PortfolioGenerationError("at least one generation artifact is required")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Require the canonical artifacts before advancing the pointer

The publish CLI accepts any nonempty artifact list, so an invocation that omits portfolio-truth.json or misspells one of the consumer-required names still replaces pointer.json successfully. Deployed consumers then resolve a generation that lacks the file they expect, despite publication reporting success; validate the required artifact names and their media/contract versions before constructing the manifest.

AGENTS.md reference: src/AGENTS.md:L17-L19

Useful? React with 👍 / 👎.

Comment on lines +662 to +663
if pre_pointer_check is not None:
pre_pointer_check()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Hold source validation through pointer replacement

When the security receipt collector or producer checkout changes concurrently, it can do so after pre_pointer_check() returns but before the later os.replace, allowing the pointer to publish a generation bound to evidence that is no longer current. The security receipt code already exposes a shared verified-binding lock for this purpose; the final validation needs to remain protected through the pointer commit rather than ending before it.

AGENTS.md reference: AGENTS.md:L65-L70

Useful? React with 👍 / 👎.

Comment on lines +401 to +409
) -> dict[str, Any]:
if security.state != "fresh":
raise PortfolioGenerationError("security binding must be fresh")
if security.producer_commit != producer.commit:
raise PortfolioGenerationError("security and producer commits disagree")
if security.producer_repository != producer.repository:
raise PortfolioGenerationError("security and producer repositories disagree")
evaluated = _parse_instant(security.evaluated_at, field="security evaluated_at")
valid_until = _parse_instant(security.valid_until, field="security valid_until")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Validate provenance fields in the public publisher

Programmatic callers of publish_generation can supply a SecurityBinding with state="fresh" but a failed terminal state, malformed hashes, an uncontrolled terminal receipt, or invalid producer receipt metadata, and this function will still advance the canonical pointer because only freshness and repository/commit agreement are checked. Since resolve_current also does not validate these nested fields, the resulting false provenance remains accepted; enforce the same binding invariants used by the CLI loaders inside the publication boundary.

AGENTS.md reference: src/AGENTS.md:L5-L10

Useful? React with 👍 / 👎.

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