Skip to content

refactor(action): simplify v2 flow to CLI incremental/full contract - #69

Open
ivanmilevtues wants to merge 13 commits into
mainfrom
action-v2-contract-only-simplification
Open

refactor(action): simplify v2 flow to CLI incremental/full contract#69
ivanmilevtues wants to merge 13 commits into
mainfrom
action-v2-contract-only-simplification

Conversation

@ivanmilevtues

@ivanmilevtues ivanmilevtues commented Aug 3, 2026

Copy link
Copy Markdown
Member

Summary

  • Remove action-local analysis orchestration and route sync/review through the CodeBoarding CLI incremental/full contract.
  • Replace engine adapter/component/build/feedback scripts with action-local, no-analysis wrapper scripts.
  • Retain OIDC relay, sync delivery strategies, bot-loop guards, and review sticky-comment behavior.
  • Preserve compatibility inputs (changed_only, render_depth) as deprecated no-op flags.

Scope

Action-only updates in CodeBoarding-action.

@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: 363744fac4

ℹ️ 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 action.yml
Comment on lines 280 to +282
set -euo pipefail
AUTH_FILE="${RUNNER_TEMP}/openrouter-auth.json"
trap 'rm -f "$AUTH_FILE"' EXIT

_strip() { printf '%s' "$1" | tr -d '[:space:]' | sed -e 's/^"//;s/"$//' -e "s/^'//;s/'\$//"; }
# Cache keys reject some characters (model slugs carry '/'); sanitize for them.
_safe() { printf '%s' "$1" | tr -c 'A-Za-z0-9._-' '_'; }

KEY="$(_strip "$RAW_KEY")"
LICENSE="$(_strip "$RAW_LICENSE")"
PROXY_URL="$(_strip "$RAW_PROXY_URL")"
PROXY_URL="${PROXY_URL%/}" # no trailing slash; engine appends /chat/completions
AGENT_MODEL="$(_strip "$RAW_AGENT_MODEL")"
PARSING_MODEL="$(_strip "$RAW_PARSING_MODEL")"
umask 077

# Three credential modes, in precedence order:
# 1. BYO key set -> talk to the provider directly (current behavior)
# 2. license_key set -> hosted proxy, bearer = the license
# 3. neither (zero-config) -> hosted proxy, bearer = a GitHub OIDC JWT
# Modes 2 & 3 force provider=openrouter and point the engine's
# OPENROUTER_BASE_URL at the proxy (written to cb-base-url). The proxy
# swaps in the real key, so no provider preflight here.
if [ -n "$KEY" ]; then
MODE="byokey"
elif [ -n "$LICENSE" ]; then
MODE="license"
else
MODE="oidc"
fi
echo "mode=$MODE" >> "$GITHUB_OUTPUT"
echo "Credential mode: $MODE"

# ── Hosted modes (license / oidc): provider is always OpenRouter via proxy ──
# The hosted tiers run on CodeBoarding's OpenRouter account. A loopback relay
# mints a fresh GitHub OIDC JWT for every engine request, then forwards it to
# the hosted proxy. This matters because an analysis can outlive a single OIDC
# JWT. To use a DIFFERENT provider, set llm_api_key (BYO-key mode, below).
if [ "$MODE" != "byokey" ]; then
if [ -z "$PROXY_URL" ]; then
echo "::error::proxy_url is empty but no llm_api_key was provided. Set llm_api_key, or restore proxy_url."
exit 1
fi
# Warn if the user asked for a non-OpenRouter provider but gave no key:
# the hosted tier can only use OpenRouter, so llm_provider is ignored here.
PROVIDER_NORM="$(printf '%s' "$RAW_PROVIDER" | tr '[:upper:]' '[:lower:]' | tr -cd 'a-z0-9_')"
if [ -n "$PROVIDER_NORM" ] && [ "$PROVIDER_NORM" != "openrouter" ]; then
echo "::warning::llm_provider='$PROVIDER_NORM' is ignored on the free/license hosted tier (OpenRouter only). To use $PROVIDER_NORM, pass its key via llm_api_key."
fi
PROVIDER_ENV="OPENROUTER_API_KEY"
AGENT_MODEL="${AGENT_MODEL:-google/gemini-3-flash-preview}"
PARSING_MODEL="${PARSING_MODEL:-google/gemini-3.1-flash-lite-preview}"

# ACTIONS_ID_TOKEN_REQUEST_URL/_TOKEN are injected into the runner process
# env (NOT the `env` context) only when the job grants `id-token: write`.
# Pass them to the local relay through its inherited environment; it requests
# a new JWT per forwarded request instead of freezing one into the engine.
if [ -z "${ACTIONS_ID_TOKEN_REQUEST_URL:-}" ] || [ -z "${ACTIONS_ID_TOKEN_REQUEST_TOKEN:-}" ]; then
echo "::error::No GitHub OIDC token available. Add \`permissions: id-token: write\` to the job (the hosted tier — free and license — needs the OIDC token to identify your repository; an llm_api_key avoids the proxy entirely)."
exit 1
fi
RELAY_READY="${RUNNER_TEMP}/cb-oidc-relay-port"
RELAY_PID_FILE="${RUNNER_TEMP}/cb-oidc-relay.pid"
RELAY_LICENSE_FILE="${RUNNER_TEMP}/cb-oidc-relay-license"
RELAY_LOG="${RUNNER_TEMP}/cb-oidc-relay.log"
rm -f "$RELAY_READY" "$RELAY_PID_FILE" "$RELAY_LICENSE_FILE" "$RELAY_LOG"
relay_args=(--upstream-base-url "$PROXY_URL" --ready-file "$RELAY_READY")
if [ "$MODE" = "license" ]; then
echo "::add-mask::$LICENSE"
printf '%s' "$LICENSE" > "$RELAY_LICENSE_FILE"
relay_args+=(--license-file "$RELAY_LICENSE_FILE")
fi
python3 "$ACTION_PATH/scripts/oidc_relay.py" "${relay_args[@]}" >"$RELAY_LOG" 2>&1 &
RELAY_PID=$!
printf '%s' "$RELAY_PID" > "$RELAY_PID_FILE"
for _ in $(seq 1 50); do
[ -s "$RELAY_READY" ] && break
kill -0 "$RELAY_PID" 2>/dev/null || break
sleep 0.1
done
if [ ! -s "$RELAY_READY" ]; then
echo "::error::Failed to start the GitHub OIDC relay."
sed -n '1,20p' "$RELAY_LOG" || true
exit 1
fi
RELAY_PORT="$(cat "$RELAY_READY")"
case "$RELAY_PORT" in *[!0-9]*|'') echo "::error::OIDC relay returned an invalid port."; exit 1 ;; esac
printf '%s' 'github-actions-oidc-relay' > "${RUNNER_TEMP}/cb-llm-key"
printf '%s' "$PROVIDER_ENV" > "${RUNNER_TEMP}/cb-provider-env"
printf '%s' "http://127.0.0.1:${RELAY_PORT}" > "${RUNNER_TEMP}/cb-base-url"
printf '%s' "$AGENT_MODEL" > "${RUNNER_TEMP}/cb-agent-model"
printf '%s' "$PARSING_MODEL" > "${RUNNER_TEMP}/cb-parsing-model"
if [ "$MODE" = "license" ]; then
echo "Using CodeBoarding license via a GitHub OIDC relay (token refreshed per request)."
else
echo "Using the free hosted tier via a GitHub OIDC relay (token refreshed per request)."
fi
exit 0
if [ -z "${ACTIONS_ID_TOKEN_REQUEST_URL:-}" ] || [ -z "${ACTIONS_ID_TOKEN_REQUEST_TOKEN:-}" ]; then
echo "::error::Missing OIDC token. Add permissions: id-token: write." && exit 1

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 Preserve BYO-key runs before requiring OIDC

The relay now unconditionally fails when the job lacks id-token: write, but both checked repository workflows grant no such permission and instead pass the now-removed llm_api_key input (.github/workflows/codeboarding.yml:123-126 and codeboarding-sync.yml:145-159). Consequently, every dogfood review and sync run fails here before analysis, and existing BYO-key consumers regress similarly; either retain the direct-key path or update the workflows and compatibility contract to mint OIDC tokens.

Useful? React with 👍 / 👎.

Comment thread action.yml Outdated
Comment on lines +786 to +788
```mermaid
$(cat "${{ steps.review_render.outputs.diagram_md }}")
```

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 Insert the Mermaid content rather than a shell expression

Action inputs under with.message are plain YAML strings and are not evaluated by a shell, so successful reviews post the literal text $(cat "/tmp/.../diagram.md") instead of a diagram. The generated file already contains its own Mermaid fences, so its contents should be placed into an output/body before invoking the comment action rather than wrapping a command substitution in another fence.

Useful? React with 👍 / 👎.

Comment thread action.yml
Comment on lines +503 to +506
PR_TITLE="${{ inputs.sync_pr_title }} $(git rev-parse --short "$TARGET_SHA")"
PR_URL="$(gh pr list --repo "$REPO" --head "$SYNC_PR_BRANCH" --base "$TARGET_BRANCH" --state open --json url --jq '.[0].url // empty' || true)"
if [ -z "$PR_URL" ]; then
gh pr create --repo "$REPO" --head "$SYNC_PR_BRANCH" --base "$TARGET_BRANCH" --title "$PR_TITLE" --body "CodeBoarding sync PR for ${TARGET_BRANCH}." >/dev/null 2>&1 || true

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 Export the token before invoking gh

When sync_strategy=pull_request, the branch push authenticates through the URL, but this step never exports GH_TOKEN or GITHUB_TOKEN for the subsequent gh pr list/create calls. GitHub does not automatically expose an action input as an environment variable, so normal callers that only provide push_token push the sync branch but fail to open its PR; all failures are swallowed and the step misleadingly reports committed=true. Restore GH_TOKEN: ${{ inputs.push_token }} on this step.

Useful? React with 👍 / 👎.

Comment on lines +41 to +44
candidate = Path(path)
if not candidate.is_absolute():
candidate = Path(output_dir) / candidate
return candidate

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 Resolve relative analysis paths from the command working directory

When the CLI returns a relative path such as out/analysis.json, it is relative to the subprocess working directory (output_dir.parent), but this code prefixes output_dir and looks for out/out/analysis.json. The newly added success test exercises exactly this contract and fails for that reason; resolve relative paths against the same working directory used by _run_command so valid CLI output does not abort analysis.

Useful? React with 👍 / 👎.

Comment thread action.yml
Comment on lines +446 to +448
git config user.name "codeboarding-review[bot]"
git config user.email "codeboarding-review[bot]@users.noreply.github.com"
git add "$OUTPUT_DIR" 2>/dev/null || true

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 Stage the generated architecture document

The render step writes docs/development/architecture.md, but this git add stages only .codeboarding. Therefore sync commits and rolling PRs never include the generated architecture document, even though the repository workflow explicitly treats it as generated output; add that path to the staged set alongside the output directory.

Useful? React with 👍 / 👎.

Comment thread action.yml Outdated
Comment on lines +704 to +705
if [ -n "$BASE_DIR" ] && git worktree list | awk '{print $1}' | grep -q "$BASE_DIR"; then
git worktree remove --force "$BASE_DIR" >/dev/null 2>&1 || true

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 Keep the committed baseline alive until rendering completes

On the normal warm-baseline path, BASE_FOR_DIFF points to $BASE_DIR/.codeboarding/analysis.json, but this removes the base worktree before publishing that path to the render step. Removing the worktree deletes the referenced analysis file, so every review that successfully reuses a committed baseline subsequently fails with Review baseline missing; copy the baseline to scratch storage or defer worktree removal until after rendering.

Useful? React with 👍 / 👎.

Comment thread action.yml
Comment on lines +436 to 437
rm -rf "$OUTPUT_DIR"
mkdir -p "$OUTPUT_DIR" "$OUTPUT_DIR/health"

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 Preserve user-authored CodeBoarding configuration

Sync now recursively deletes the entire .codeboarding directory before recreating generated files, so tracked user inputs such as .codeboarding/.codeboardingignore, health/.healthignore, and health/health_config.json are staged as deletions and removed from the repository. The README and sync workflow explicitly distinguish these inputs from generated artifacts; delete only owned generated files as the previous implementation did.

Useful? React with 👍 / 👎.

Comment thread scripts/run_local.sh
Comment on lines +89 to +92
if [ -d "$OUT" ]; then
rm -rf "$OUT"
mkdir -p "$OUT"
fi

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 Do not recursively erase the caller's local output directory

In repository-analysis mode, --out is caller-controlled and may point to an existing directory, but this now deletes that directory wholesale before creating the harness workspace. A command such as run_local.sh --out /tmp/project-output ... destroys unrelated contents, and accidentally setting --out to the analyzed repository can delete the repository itself; clear only action-owned subdirectories or require an empty dedicated output path.

Useful? React with 👍 / 👎.

Comment thread action.yml
Comment on lines +737 to +742
N_CHANGED="$(jq -r '.n_changed' "$META")"
TRUNCATED="$(jq -r '.truncated | ascii_downcase' "$META")"
echo "diagram_md=$DIAGRAM_OUT" >> "$GITHUB_OUTPUT"
echo "n_changed=$N_CHANGED" >> "$GITHUB_OUTPUT"
echo "truncated=$TRUNCATED" >> "$GITHUB_OUTPUT"
echo "rendered=true" >> "$GITHUB_OUTPUT"

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 Honor the renderer's rendered flag

When the analyses are identical or the graph cannot be rendered within limits, diff_to_mermaid.py writes an empty file and reports rendered=false, but this step ignores that field and unconditionally emits rendered=true. The upload and comment steps then run with an empty diagram while the metadata may misleadingly report an auto-trimmed render; parse .rendered and gate publication on its actual value.

Useful? React with 👍 / 👎.

Comment thread action.yml
Comment on lines +446 to +448
git config user.name "codeboarding-review[bot]"
git config user.email "codeboarding-review[bot]@users.noreply.github.com"
git add "$OUTPUT_DIR" 2>/dev/null || true

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 Force-add action-owned artifacts when callers ignore them

Cold-start syncs fail silently in repositories whose .gitignore excludes .codeboarding/: git add rejects the generated untracked files, stderr and the nonzero status are swallowed, and the following cached-diff check reports that architecture is unchanged. The previous implementation used git add -f -A for action-owned generated paths; retain forced staging so common cache-ignore rules do not disable baseline delivery.

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: b9dc7b6a94

ℹ️ 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 action.yml Outdated
uses: actions/setup-node@v4
with:
node-version: '20'
python-version: '3.13'

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 Keep the runner on Python 3.12

With the default codeboarding_version still pinned to 0.13.4, selecting Python 3.13 makes the following pip install unable to resolve that release: its langchain-cerebras>=0.8 dependency is published for Python <3.13. The previous setup deliberately selected 3.12 for this constraint, so default sync and review runs now stop during installation before any analysis starts.

Useful? React with 👍 / 👎.

Comment thread action.yml
esac
[ -n "$ISSUE_PR_URL" ] || skip "Not a pull request comment."

PR_JSON="$(gh api "$ISSUE_PR_URL")"

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 Authenticate gh before resolving slash commands

On every trusted issue_comment invocation, this is the first gh call, but the guard step no longer exports GH_TOKEN or GITHUB_TOKEN; passing github_token as a composite-action input does not create either environment variable. Consequently /codeboarding runs fail here with an authentication error instead of resolving the PR. The GitHub CLI environment documentation identifies GH_TOKEN and GITHUB_TOKEN as the authentication variables for API requests, so this step needs to map inputs.github_token to one of them.

Useful? React with 👍 / 👎.

Comment thread action.yml
Comment on lines 246 to +249
uses: actions/checkout@v4
with:
repository: ${{ steps.guard.outputs.checkout_repo }}
path: target-repo
token: ${{ inputs.github_token }}
ref: ${{ steps.guard.outputs.checkout_ref || github.sha }}

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 Checkout fork heads from the head repository

For a pull request from a fork, checkout_ref is the fork's head SHA, but this checkout omits repository, so actions/checkout defaults to github.repository (the upstream base repository). That SHA is not on the upstream repository's normal branches or tags, causing checkout to fail before the later fork-aware fetch and analysis logic can run. Pass steps.guard.outputs.head_repo for review mode, as required by the documented checkout repository input.

Useful? React with 👍 / 👎.

Comment thread action.yml
LICENSED_FLAG="--licensed"; MAX_DEPTH=10; TIER="licensed"
else
LICENSED_FLAG=""; MAX_DEPTH=3; TIER="free-tier"
RELAY_ARGS=(--upstream-base-url https://openrouter.ai/api/v1 --ready-file "$READY")

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 Route OIDC requests through the CodeBoarding proxy

When OIDC or license authentication is used, the relay replaces the request's authorization header with a GitHub OIDC JWT (optionally suffixed with the CodeBoarding license), but this now forwards that bearer directly to OpenRouter. OpenRouter expects an OpenRouter API key and does not validate the CodeBoarding OIDC/license format; the relay is designed to target the hosted CodeBoarding proxy that validates the JWT and substitutes the real provider key. Thus every hosted-tier analysis reaches the model API with invalid credentials even after id-token: write is configured.

Useful? React with 👍 / 👎.

Comment thread action.yml
id: sync_commit
if: always() && steps.guard.outputs.skip != 'true' && steps.guard.outputs.mode == 'sync'

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 Commit sync artifacts only after rendering succeeds

If Render sync docs fails after analysis succeeds, this always() condition still runs the commit step. Because the failed render never publishes docs_dir, the step deletes the existing .codeboarding tree, ignores the empty markdown copy, copies only the analysis artifacts, and can commit and push the deletion of all rendered documentation despite the workflow already being failed. Gate this step on a successful sync_render outcome so a renderer failure cannot deliver a partial baseline.

Useful? React with 👍 / 👎.

Comment thread action.yml
--analysis "${{ steps.sync_analyze.outputs.analysis_path }}" \
--output-dir "$DOC_DIR" \
--repo-name "${{ github.repository }}" \
--repo-ref "${{ steps.guard.outputs.target_sha }}" \

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 Pass a source URL prefix to the documentation renderer

On every sync, repo_ref is now only the raw commit SHA, although the unchanged render_docs API uses this value as the prefix for generated source-file links; the previous flow supplied a GitHub blob URL containing the repository, branch, and output path. The resulting markdown therefore contains relative links beginning with a SHA instead of links to repository source. Build the full https://github.com/<repo>/blob/<ref>/... prefix before calling the renderer.

Useful? React with 👍 / 👎.

Comment thread action.yml Outdated

See the [setup guide](https://github.com/CodeBoarding/CodeBoarding-action#more-usage) for the exact workflow snippet.
**Hosted webview:** [open artifact](${{ steps.upload_review_artifact.outputs.artifact-url }})

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 Link to the hosted webview rather than the artifact

For every successful review, artifact-url is the GitHub Actions artifact URL, not a CodeBoarding webview URL, so the link labeled “Hosted webview” opens or downloads the artifact instead of showing the interactive architecture view promised by the action. The previous flow constructed the URL from webview_base_url and the run metadata; retain that URL construction and keep the artifact URL as a separate download link.

Useful? React with 👍 / 👎.

Comment thread action.yml
echo "target_sha=$GITHUB_SHA" >> "$GITHUB_OUTPUT"
echo "target_branch=$REF_NAME" >> "$GITHUB_OUTPUT"
echo "checkout_ref=$GITHUB_SHA" >> "$GITHUB_OUTPUT"
echo "commit_message=${{ inputs.commit_message }}" >> "$GITHUB_OUTPUT"

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 Pass commit messages through the environment

When a caller customizes commit_message with shell syntax such as backticks or $(...), direct expression substitution places that text inside the generated Bash program, where it is executed rather than retained as commit-message text; a multiline message can also inject additional entries into GITHUB_OUTPUT. Treat the action input as data by mapping it through env and use the multiline output form if it must be forwarded to another step.

Useful? React with 👍 / 👎.

Comment thread scripts/run_local.sh
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
<pre class=\"mermaid\">\n{graph}\n</pre>
<script type=\"module\">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.js';

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 Import the existing Mermaid ESM bundle

Every generated local preview imports mermaid.esm.min.js, but Mermaid 10 publishes the ESM bundle at dist/mermaid.esm.min.mjs; the new .js URL returns no module, leaving preview.html with an unrendered Mermaid source block. Restore the .mjs bundle path so the documented local preview works in the browser.

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: 4ecc8286dc

ℹ️ 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 action.yml
Comment on lines +675 to +678
if [ "$HAS_BASELINE" = "true" ]; then
BASE_FOR_DIFF="$BASE_DIR/.codeboarding/analysis.json"
elif [ -n "$BASE_FULL_PATH" ] && [ -f "$BASE_FULL_PATH" ]; then
BASE_FOR_DIFF="$BASE_FULL_PATH"

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 Use the rebuilt base after a full fallback

When a committed baseline exists but incremental analysis returns requires_full_analysis=true—for example after an incompatible baseline-format upgrade—the step creates a fresh base analysis in BASE_FULL_PATH, but this branch still selects the original baseline merely because HAS_BASELINE remains true. After the head is analyzed using the rebuilt state, rendering therefore compares it with the stale baseline that triggered the fallback, which can fail or report spurious changes; prefer BASE_FULL_PATH whenever the base fallback ran.

Useful? React with 👍 / 👎.

Comment thread action.yml
Comment on lines +245 to 246
- name: Checkout
uses: actions/checkout@v4

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 Stop after the guard soft-skips the run

When the guard deliberately soft-skips an unsupported event, tag push, or bot-owned sync commit, this checkout and the following Python setup and package installation still run because none is conditioned on steps.guard.outputs.skip. A run documented as skipped can therefore spend several minutes downloading dependencies or even fail on checkout/PyPI problems; gate these preparation steps on skip != 'true' as the analysis steps are.

Useful? React with 👍 / 👎.

Comment thread action.yml
fi

PR_TITLE="${{ inputs.sync_pr_title }} $(git rev-parse --short "$TARGET_SHA")"

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 Treat sync PR titles as data

When a caller customizes sync_pr_title with shell syntax such as backticks, $(...), or a double quote, GitHub substitutes the input into this Bash program before execution, so the title can execute commands or break the step instead of remaining PR-title text. Pass this separate input through env and expand the environment variable inside the quoted assignment.

Useful? React with 👍 / 👎.

Comment thread action.yml Outdated
printf '%s' "$DIFF" > "$META"

N_CHANGED="$(jq -r '.n_changed' "$META")"
TRUNCATED="$(jq -r '.truncated | ascii_downcase' "$META")"

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 Read the truncated flag without a string filter

diff_to_mermaid.py serializes truncated as a JSON boolean, but ascii_downcase only accepts strings; with jq 1.7, even { "truncated": false } fails here with explode input must be a string. Consequently every review that reaches this step exits before publishing its render outputs, artifact, or success comment; read the boolean directly with jq -r '.truncated' or convert it using tostring first.

Useful? React with 👍 / 👎.

Comment thread action.yml
fi

PR_TITLE="${{ inputs.sync_pr_title }} $(git rev-parse --short "$TARGET_SHA")"
PR_URL="$(gh pr list --repo "$REPO" --head "$SYNC_PR_BRANCH" --base "$TARGET_BRANCH" --state open --json url --jq '.[0].url // empty' || true)"

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 Exclude fork PRs from the rolling-PR lookup

When a contributor has an open fork PR whose head branch is also named codeboarding/sync and whose base matches TARGET_BRANCH, this bare --head lookup can return that cross-repository PR first. The action then skips creating a PR for the machine-owned branch it just pushed and reports the contributor's URL and number instead, allowing an accidental or deliberately named fork branch to block rolling-baseline delivery; retain the previous isCrossRepository == false filter when selecting the PR.

Useful? React with 👍 / 👎.

Comment thread action.yml
Comment on lines +291 to +293
: > "$LICENSE_FILE"
if [ -n "${LICENSE_KEY:-}" ]; then
printf '%s' "$LICENSE_KEY" > "$LICENSE_FILE"

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 Restrict permissions on the relay license file

On a multi-user self-hosted runner with the usual 0022 umask and a traversable runner temp directory, this creates license.txt as mode 0644, leaving the CodeBoarding license readable by other local users for the duration of the analysis—and potentially longer if the job is canceled before cleanup. Set umask 077 before creating the relay directory/files or explicitly chmod the license file to 0600, as the previous credential setup did.

Useful? React with 👍 / 👎.

@ivanmilevtues

Copy link
Copy Markdown
Member Author

/codeboarding

@ivanmilevtues

Copy link
Copy Markdown
Member Author

/codeboarding

@codeboarding-review

codeboarding-review Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Architecture review

Status: 5 changed component(s)
Mode: incremental
Render: full top-level

graph LR
    n_Visual_Rendering_Engine["Visual Rendering Engine"]
    n_Structural_Diff_Engine["Structural Diff Engine"]
    n_Interaction_Orchestrator["Interaction Orchestrator"]
    del_Analysis_Engine_Adapter["Analysis Engine Adapter"]
    del_Telemetry_Feedback_Handler["Telemetry #38; Feedback Handler"]
    n_Visual_Rendering_Engine -- "Requests interactive metadata for diagram nodes" --> n_Interaction_Orchestrator
    n_Structural_Diff_Engine -- "Provides change-set data" --> n_Visual_Rendering_Engine
    n_Structural_Diff_Engine -- "Supplies component identity for link resolution" --> n_Interaction_Orchestrator
    del_Analysis_Engine_Adapter -- "Passes repository context for CTA generation" --> n_Interaction_Orchestrator
    n_Visual_Rendering_Engine -- "Queries for architectural changes" --> n_Structural_Diff_Engine
    n_Interaction_Orchestrator -- "Consumes issue counts for UI" --> n_Visual_Rendering_Engine
    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;
    class n_Visual_Rendering_Engine,n_Structural_Diff_Engine,n_Interaction_Orchestrator modified;
    class del_Analysis_Engine_Adapter,del_Telemetry_Feedback_Handler deleted;
    linkStyle 0,2 stroke:#0b5d23,stroke-width:2px;
    linkStyle 3,4,5 stroke:#82071e,stroke-width:2px,stroke-dasharray:5 3;
Loading

Hosted webview: open artifact

run 30858031112 · attempt 1

@ivanmilevtues

Copy link
Copy Markdown
Member Author

/codeboarding

@ivanmilevtues

Copy link
Copy Markdown
Member Author

/codeboarding

@ivanmilevtues

Copy link
Copy Markdown
Member Author

/codeboarding

@ivanmilevtues

Copy link
Copy Markdown
Member Author

/codeboarding

@ivanmilevtues

Copy link
Copy Markdown
Member Author

/codeboarding

@ivanmilevtues

Copy link
Copy Markdown
Member Author

/codeboarding

@ivanmilevtues

Copy link
Copy Markdown
Member Author

/codeboarding

@ivanmilevtues

Copy link
Copy Markdown
Member Author

/codeboarding

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

ℹ️ 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 action.yml
Comment on lines +512 to +514
PR_URL="$(gh pr list --repo "$REPO" --head "$SYNC_PR_BRANCH" --base "$TARGET_BRANCH" --state open --json url --jq '.[0].url // empty' || true)"
if [ -z "$PR_URL" ]; then
gh pr create --repo "$REPO" --head "$SYNC_PR_BRANCH" --base "$TARGET_BRANCH" --title "$PR_TITLE" --body "CodeBoarding sync PR for ${TARGET_BRANCH}." >/dev/null 2>&1 || true

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 Refresh the title of an existing rolling PR

On the second and subsequent pull_request syncs, this lookup returns the existing PR URL, so the creation block is skipped and the newly computed PR_TITLE is never applied. The machine branch is still force-updated, but the open PR's title permanently advertises the target SHA from its first run, misleading reviewers about which source revision the rolling baseline represents; edit the existing PR's title after the lookup.

Useful? React with 👍 / 👎.

Comment thread action.yml
LLM_API_KEY="$(printf '%s' "$LLM_API_KEY" | tr -d '[:space:]' | sed -e 's/^"//;s/"$//' -e "s/^'//;s/'\$//")"
LLM_API_KEY="${LLM_API_KEY#OPENROUTER_API_KEY=}"
echo "::add-mask::$LLM_API_KEY"
echo "OPENROUTER_API_KEY=$LLM_API_KEY" >> "$GITHUB_ENV"

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 Clear the OpenRouter key before running output steps

When llm_api_key is supplied, writing it to GITHUB_ENV makes the real API credential available to every subsequent step in the caller's job, including the artifact-upload and sticky-comment third-party actions, and the final cleanup never overwrites or unsets it. The previous flow dropped key material immediately after analysis; scope this environment variable to the analysis commands or clear it before entering the output phase so BYO credentials are not exposed beyond the engine.

Useful? React with 👍 / 👎.

Comment thread action.yml
# retries: another push may land on target_branch while the analysis runs.
# Fail-open on final rejection — the next repository change regenerates. ----
git commit -m "$COMMIT_MESSAGE" >/dev/null
AUTH_URL="https://x-access-token:${push_token}@github.com/${REPO}.git"

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 Build the sync remote from github.server_url

When this action runs on GitHub Enterprise Server, the repository lives under github.server_url, but the direct-push remote is hardcoded to github.com. Every otherwise successful sync therefore attempts to push OWNER/REPO to the public GitHub host and reports committed=false; construct the authenticated remote from ${{ github.server_url }} as the previous delivery flow did.

Useful? React with 👍 / 👎.

@ivanmilevtues

Copy link
Copy Markdown
Member Author

/codeboarding

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