Skip to content

feat: keep the diagram on a baseline branch of its own - #142

Open
Svilen-Stefanov wants to merge 1 commit into
feat/ancestor-base-seedfrom
feat/baseline-branch
Open

Svilen-Stefanov wants to merge 1 commit into
feat/ancestor-base-seedfrom
feat/baseline-branch

Conversation

@Svilen-Stefanov

Copy link
Copy Markdown
Contributor

Stacked on #140 (feat/ancestor-base-seed), which is stacked on #139. Review and merge those first.

What changed and why

Section 5 of the base-provenance contract: keep the diagram on a branch of its own, so a team gets a saved diagram without committing generated files to its code branch. New setups will default to it through the webview's setup template (separate webview PR); this PR only adds the capability. Existing repositories keep whatever strategy they use. Migrating between the two is deferred to https://github.com/CodeBoarding/CodeBoarding-webview/issues/199.

  • sync_strategy: branch and a new baseline_branch input (default codeboarding/baseline). The first sync creates the branch as an orphan. Each sync adds one commit with the same .codeboarding/ files sync commits today plus .codeboarding/source.json (schema, source_branch, source_sha, generated_at, engine_version), titled chore(codeboarding): diagram of main @<sha7> with a CodeBoarding-Source: <sha> trailer. Engine output is never edited.
  • Delivery (deliver-sync.sh) builds the commit with a scratch index, never touches the target branch (no .gitattributes either), and pushes fast-forward only, never forced. Races: a target that moved during analysis drops the result (as today); a baseline branch moved by a concurrent sync is built on once; a re-run for the same commit adds nothing. A push refused while the branch tip did not move fails with: GitHub refused the push to codeboarding/baseline, most likely because a branch rule protects it. Add the CodeBoarding app as a bypass actor for codeboarding/baseline in the repository's rulesets, or set sync_strategy: push.
  • Sync seeds from the branch tip, then runs incrementally. Without the branch it falls through to the ancestor-artifact lookup from feat: catch up the review base from the nearest saved ancestor #140, then full, and delivery recreates the branch.
  • Review base order: exact artifact, committed at merge base, baseline branch, ancestor artifacts, full. The branch's newest 100 commits are fetched without blobs into a scratch repo (messages only), and their trailers are matched against the merge base's first-parent history (100 deep). An exact entry is base_source=saved; an ancestor entry is caught up incrementally and reported as ancestor with its catch-up count. base_from_sha is the source sha. A base read from the branch is published under the merge base's artifact name.
  • Guard: accepts branch; ignores pushes to the baseline branch itself.
  • Docs: README section and input row; docs/COMMIT_STRATEGY.md "The baseline branch" (what lives where, how sync writes and reviews read it, both bounds, what a deleted branch means, private repos need a paid plan for rulesets); docs/baseline-branch-ruleset.json to import (blocks deletion and non-fast-forward on codeboarding/baseline, CodeBoarding Review app id 4021464 as bypass actor).

What it looks like

This PR changes nothing visible in the web platform by itself; the webview PR that reads the branch comes separately. On GitHub, the new branch's commits read:

chore(codeboarding): diagram of main @a1b2c3d

CodeBoarding-Source: a1b2c3d4e5f6...

How it was tested

tests/test_baseline_branch.py against real local remotes: first sync creates an orphan with source.json and the trailer and leaves main alone; the second sync appends a fast-forward commit; a same-commit re-run adds nothing; a pre-receive hook refusing the branch produces the plain message; a deleted branch is recreated as a new orphan; a target that moved keeps the branch unchanged; a review resolves saved from an exact branch entry and ancestor (catch-up 1) from an older one, from a depth-1 clone; a missing branch falls back to computed; sync continues from the branch tip; guard accepts the strategy and skips pushes to the branch.

python -m unittest discover -s tests: 226 tests, all pass locally (macOS). Black 25.9.0 via the pre-commit hook; shellcheck on all action scripts.

🤖 Generated with Claude Code

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 7, 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-10-07T15:40:27.725374Z f5c9e48 New commits
ℹ️ 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.

@codeboarding-review

codeboarding-review Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

CodeBoarding review

Status: 0 changed components (no analysed file changed)

See the full change in CodeBoarding.

Base: caught up 4 commits from feat/ancestor-base-seed @a7675d5, 32 s · changes 9 s

graph LR
    n_action_scripts["action_scripts"]
    classDef added fill:#1f883d,stroke:#0b5d23,color:#ffffff;
    classDef modified fill:#bf8700,stroke:#7d4e00,color:#ffffff;
    classDef deleted fill:#cf222e,stroke:#82071e,color:#ffffff,stroke-dasharray:5 3;
Loading

download artifacts · run 37644784145

@Svilen-Stefanov
Svilen-Stefanov force-pushed the feat/ancestor-base-seed branch from 2012a60 to 32fdc42 Compare October 7, 2026 15:31
sync_strategy: branch writes the analysis to an orphan branch,
codeboarding/baseline by default (the new baseline_branch input), and never
writes the target branch. Each sync adds one fast-forward commit with the
same .codeboarding/ files plus .codeboarding/source.json, titled
"chore(codeboarding): diagram of <branch> @<sha7>" with a
CodeBoarding-Source trailer. A target that moved during analysis drops the
result as today; a branch moved by a concurrent sync is built on once; a
push refused while the tip did not move fails with the branch rule and the
fix. Sync seeds from the branch tip; without one it seeds from a saved
ancestor or runs full, and recreates the branch.

Reviews read the branch after an exact artifact and a baseline committed at
the merge base: a blobless fetch of its newest 100 commits, matched by
trailer against the merge base's first-parent history. An entry for the
merge base is saved; one for an ancestor is caught up and reported as
ancestor. A base read from the branch is published under the merge base's
name.

Docs cover the layout, a deleted branch, and an importable ruleset.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@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: db578a35b9

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread scripts/action/analyze.sh
Comment on lines +369 to +370
elif [ "$BRANCH_DISTANCE" -eq 0 ]; then
REQUIRES_FULL=false base_source=saved base_from_sha="$BRANCH_SOURCE" catchup_commits=0

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 Reject exact baselines from incompatible configurations

When the baseline branch contains an entry for the merge base, this path accepts it after checking only depth_cap and skips the compatibility run. Baseline artifacts are otherwise keyed by CFG_HASH, which also covers the engine version, provider, endpoint, region, and model inputs; after an engine upgrade or when sync and review use different models, the review therefore compares an old-configuration base with a newly generated head and can report spurious architecture changes. Store and validate the configuration identity with each branch entry, or run the same compatibility check used for non-exact entries before treating it as saved.

Useful? React with 👍 / 👎.

Comment on lines +101 to +103
if [ -n "$tip" ]; then
git fetch -q --depth=1 "$REMOTE" "refs/heads/$branch"
parent=(-p "$tip")

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 Refuse to overwrite an existing non-baseline branch

If baseline_branch already names any ordinary branch other than target_branch—for example a pre-existing codeboarding/baseline, develop, or the old codeboarding/sync branch—this unconditionally makes its tip the parent of a commit whose tree contains only .codeboarding/. The subsequent fast-forward push succeeds and makes every other file disappear from that branch, rather than creating the promised orphan branch. Verify that an existing tip is a recognized CodeBoarding baseline before parenting it, and fail without pushing when it is not.

Useful? React with 👍 / 👎.

Comment on lines +114 to +115
# Never forced: the parent is the tip just read, so this only ever fast-forwards.
if git push -q "$REMOTE" "$commit:refs/heads/$branch"; then

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 Couple the target-head check to the baseline update

The target branch is checked by a separate fetch at the start of the loop, but this push updates only the baseline ref. If target_branch advances after that fetch and before this push, the push still succeeds and publishes an analysis of the old BASE_SHA as the latest baseline, contrary to the stale-result guarantee; the queued newer run may not repair it if that run later fails or is cancelled. The expected target SHA needs to be validated in the same remote transaction as the baseline update.

Useful? React with 👍 / 👎.

@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: f5c9e48f22

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +11 to +13
"rules": [
{ "type": "deletion" },
{ "type": "non_fast_forward" }

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 Restrict baseline writes to the bypass actor

In repositories where contributors may push branches but the main branch requires reviewed PRs, this ruleset still lets any contributor create or fast-forward codeboarding/baseline; these rules block only deletion and non-fast-forward updates. Review and sync runs later pass that branch's .codeboarding/static_analysis.pkl through restore_baseline to the engine, which loads pickle state in a privileged workflow, so a contributor can bypass code review with a crafted baseline commit. Add creation and update restrictions, leaving only the intended app/token as a bypass actor.

Useful? React with 👍 / 👎.

Comment thread scripts/action/analyze.sh
mkdir -p "$scratch" "$state"
git -C "$CHECKOUT_DIR" archive "$commit" .codeboarding | tar -x -C "$scratch" || return 1
rm -f "$scratch/.codeboarding/source.json"
cp -a "$scratch/.codeboarding/." "$state/"

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 Replace generated state when restoring the branch

When a repository switches from push to branch, $state is initially seeded with the old committed .codeboarding directory, and this overlay leaves any generated files absent from the branch snapshot untouched. Optional artifacts such as static_analysis.sha, codeboarding_version.json, or a health report can therefore come from the old code-branch baseline while analysis.json and the pickle come from the baseline branch, and that mixed state is passed to incremental analysis. Clear the generated state before copying the snapshot, then restore only the current checkout's user configuration as seed_from_ancestor does.

Useful? React with 👍 / 👎.

Comment on lines +99 to +102
tip="$(git ls-remote "$REMOTE" "refs/heads/$branch" | awk '{print $1; exit}')"
parent=()
if [ -n "$tip" ]; then
git fetch -q --depth=1 "$REMOTE" "refs/heads/$branch"

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 Use the fetched tip as the baseline parent

If another sync advances the baseline branch after ls-remote records tip but before this depth-one fetch, the fetch downloads the new tip while parent still names the old one. When that old commit is not already in the checkout—such as with force_full, or when the branch had already moved during analysis—git commit-tree -p "$tip" fails before the push and the advertised retry logic can run. git fetch -h describes --depth as producing shallow history, so derive tip from the fetched FETCH_HEAD or fetch the recorded SHA explicitly.

Useful? React with 👍 / 👎.

Comment thread scripts/action/guard.sh
Comment on lines +30 to +34
if [ "$SYNC_STRATEGY" = branch ]; then
[ -n "${BASELINE_BRANCH:-}" ] || fail "baseline_branch is required with sync_strategy: branch."
# The baseline branch holds only analysis; a workflow that also fires on it must not analyze it.
[ "$REF_NAME" != "$BASELINE_BRANCH" ] || skip "Ignoring a push to the baseline branch $BASELINE_BRANCH."
[ "$target_branch" != "$BASELINE_BRANCH" ] || fail "target_branch must differ from baseline_branch."

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 the baseline branch before analysis

If baseline_branch contains an invalid Git refname, such as one with .., a space, or a trailing dot, this guard accepts it because it checks only that the value is nonempty. The analysis lookup then silently treats the failed fetch as a missing baseline and can perform a full paid analysis, after which delivery fails with an invalid refspec and misreports the unchanged empty tip as a branch-rule rejection. Validate refs/heads/$BASELINE_BRANCH with Git's refname validator in the guard so this configuration fails before checkout and analysis.

Useful? React with 👍 / 👎.

@ivanmilevtues ivanmilevtues left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I mentally looked over the thing here. Looked through the logic and it makes sense and looks fine. no majore issues found from prompting just wording again + takea look at the codex comments. (there are some P1s)

Comment thread action.yml
description: 'Sync delivery method: push, pull_request, or branch (an orphan branch of its own, see baseline_branch).'
required: false
default: 'push'
baseline_branch:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

maybe the word baseline is not very intuitive for our users as we call this syncing, so I suppose maybe we should name it syncing_branch

Comment thread README.md
with:
mode: sync
llm: hosted
target_branch: main

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

target_branch, is this the target in tehms of where the sync will happen or in terms of which branch we will sync with, unsure that wording is clear again.

i think that most of these things will be read by ppl or even more by their agents so proly descriptive and somewhat clear names are worth investing in.

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.

2 participants