feat: fat-slices repo-architect execution path via GitHub Actions#7
feat: fat-slices repo-architect execution path via GitHub Actions#7
Conversation
- Update .github/workflows/repo-architect.yml with lane/targets/allow_dirty inputs, GITHUB_MODEL/REPO_ARCHITECT_LANE/REPO_ARCHITECT_TARGETS env exports, dynamic CLI-flag detection, bash-array quoting, and include-hidden-files artifact upload - Add scripts/run_repo_architect_slices.sh — 6-slice orchestration script with race-condition-safe run-ID polling and configurable GH_API_DELAY - Add scripts/bootstrap_repo_architect_slices.sh — local bootstrap helper Co-authored-by: Steake <530040+Steake@users.noreply.github.com>
🧪 CI — Python 3.10 |
🧪 CI — Python 3.11 |
|
Ok |
There was a problem hiding this comment.
Pull request overview
Adds a “fat slices” execution path for repo_architect.py by extending the GitHub Actions workflow interface and introducing local scripts to dispatch multiple sequential workflow runs and collect/validate their artifacts.
Changes:
- Extends
.github/workflows/repo-architect.ymlwithlane,targets, andallow_dirtyinputs; uploads hidden artifacts; and adds dynamic CLI flag detection for--lane/--targets. - Adds
scripts/run_repo_architect_slices.shto dispatch and monitor a fixed sequence of slice runs and download artifacts per run. - Adds
scripts/bootstrap_repo_architect_slices.shto (re)write the workflow and runner scripts into canonical repo locations.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
scripts/run_repo_architect_slices.sh |
New orchestrator to dispatch 6 sequential slices, watch runs, download artifacts, and summarize latest_analysis.json. |
scripts/bootstrap_repo_architect_slices.sh |
New bootstrap script that overwrites the workflow + runner script via heredocs and marks the runner executable. |
.github/workflows/repo-architect.yml |
Adds workflow inputs/env for lane/targets, conditional extra args construction, and uploads hidden files in artifacts. |
scripts/run_repo_architect_slices.sh
Outdated
| for cmd in gh python3 jq; do | ||
| if ! command -v "$cmd" &>/dev/null; then | ||
| echo "ERROR: required command '$cmd' not found." >&2 | ||
| exit 1 | ||
| fi | ||
| done |
There was a problem hiding this comment.
python3 is listed as a required dependency but this script doesn’t invoke it (JSON parsing is done with jq). Consider either removing python3 from the dependency check or using it for validation, to avoid failing on systems that otherwise have the needed tooling.
| cat > "$WORKFLOW_DIR/repo-architect.yml" << 'WORKFLOW_EOF' | ||
| name: repo-architect | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| inputs: | ||
| mode: |
There was a problem hiding this comment.
This bootstrap script embeds full copies of both the workflow and runner script as heredocs and overwrites the tracked files each time it’s run. That duplication can easily drift from the committed versions (or accidentally wipe local edits). Consider generating these files by copying from the tracked paths (or by keeping a single source of truth) so the bootstrap step can’t get out of sync.
.github/workflows/repo-architect.yml
Outdated
| GITHUB_MODEL: ${{ github.event.inputs.github_model || 'openai/gpt-4.1' }} | ||
| REPO_ARCHITECT_LANE: ${{ github.event.inputs.lane || '' }} | ||
| REPO_ARCHITECT_TARGETS: ${{ github.event.inputs.targets || '' }} | ||
| run: | | ||
| MODE="${{ github.event.inputs.mode }}" | ||
| MODEL="${{ github.event.inputs.github_model }}" | ||
| REPORT_PATH="${{ github.event.inputs.report_path }}" | ||
| MUTATION_BUDGET="${{ github.event.inputs.mutation_budget }}" | ||
| ALLOW_DIRTY="${{ github.event.inputs.allow_dirty }}" | ||
| if [ -z "$MODE" ]; then MODE="report"; fi | ||
| if [ -z "$MODEL" ]; then MODEL="openai/gpt-4.1"; fi | ||
| if [ -z "$REPORT_PATH" ]; then REPORT_PATH="docs/repo_architect/runtime_inventory.md"; fi | ||
| if [ -z "$MUTATION_BUDGET" ]; then MUTATION_BUDGET="1"; fi | ||
| export GITHUB_MODEL="$MODEL" | ||
| python repo_architect.py --allow-dirty --mode "$MODE" --report-path "$REPORT_PATH" --mutation-budget "$MUTATION_BUDGET" | ||
| if [ -z "$ALLOW_DIRTY" ]; then ALLOW_DIRTY="true"; fi | ||
|
|
||
| # Detect optional --lane / --targets CLI support; fall back to env vars if absent | ||
| HELP_TEXT="$(python repo_architect.py --help 2>&1)" | ||
| EXTRA_ARGS=() | ||
| if echo "$HELP_TEXT" | grep -q -- '--lane'; then | ||
| if [ -n "$REPO_ARCHITECT_LANE" ]; then | ||
| EXTRA_ARGS+=(--lane "$REPO_ARCHITECT_LANE") | ||
| fi | ||
| fi | ||
| if echo "$HELP_TEXT" | grep -q -- '--targets'; then | ||
| if [ -n "$REPO_ARCHITECT_TARGETS" ]; then | ||
| EXTRA_ARGS+=(--targets "$REPO_ARCHITECT_TARGETS") | ||
| fi | ||
| fi |
There was a problem hiding this comment.
lane/targets inputs are exported/detected here, but repo_architect.py currently does not accept --lane/--targets and also does not read REPO_ARCHITECT_LANE / REPO_ARCHITECT_TARGETS from the environment. As a result, dispatched “slice” runs cannot actually be scoped by lane/targets (these values are effectively ignored). Consider either implementing lane/targets handling in repo_architect.py (CLI flags or env var parsing) or removing these workflow inputs/args until the backend supports them to avoid a misleading interface.
scripts/run_repo_architect_slices.sh
Outdated
| gh run download "$RUN_ID" \ | ||
| --repo "$REPO" \ | ||
| --dir "$SLICE_DIR" \ | ||
| --pattern "repo-architect-$RUN_ID" 2>/dev/null || \ | ||
| gh run download "$RUN_ID" \ | ||
| --repo "$REPO" \ | ||
| --dir "$SLICE_DIR" || true | ||
|
|
||
| # Locate the analysis JSON (may be nested under artifact folder) | ||
| ANALYSIS_FILE="$(find "$SLICE_DIR" -name "latest_analysis.json" -type f | head -1 || true)" | ||
|
|
||
| echo "" | ||
| echo "--- Validation for slice: $slice_name ---" | ||
|
|
||
| if [ -z "$ANALYSIS_FILE" ]; then | ||
| echo "WARNING: latest_analysis.json not found in downloaded artifacts." | ||
| else |
There was a problem hiding this comment.
Artifact download failures and missing latest_analysis.json are currently treated as non-fatal (|| true + WARNING). This conflicts with the script’s stated goal of “fail hard on errors” and can silently mark a slice as successful even when no artifacts were produced. Consider failing the slice if artifact download fails or if latest_analysis.json cannot be found/parsed, and assert expected mode/status values instead of only warning on mismatches.
| for attempt in $(seq 1 "$max_attempts"); do | ||
| run_id="$(gh run list \ | ||
| --repo "$REPO" \ | ||
| --workflow "$WORKFLOW_FILE" \ |
There was a problem hiding this comment.
wait_for_new_run_id selects the newest run for the workflow without filtering by branch/ref (and without verifying inputs). If another run for the same workflow starts on a different branch (e.g., the scheduled trigger), this can pick the wrong run ID even if it’s “newer” than before_id. Consider filtering gh run list by the target branch/ref (and ideally event type) or querying for the run matching the dispatch ref/created timestamp.
| --workflow "$WORKFLOW_FILE" \ | |
| --workflow "$WORKFLOW_FILE" \ | |
| --branch "$BRANCH" \ |
scripts/run_repo_architect_slices.sh
Outdated
| # --------------------------------------------------------------------------- | ||
| if [ -n "${MERGE_BASELINE_PR:-}" ]; then | ||
| echo "Merging baseline PR #$MERGE_BASELINE_PR …" | ||
| gh pr merge "$MERGE_BASELINE_PR" --repo "$REPO" --squash --auto || true |
There was a problem hiding this comment.
When MERGE_BASELINE_PR is set, merge failures are ignored (|| true), and gh pr merge --auto can return before the PR is actually merged. That means subsequent slices may run against an unexpected code baseline. Consider failing fast if the merge command fails, and/or waiting until the PR is fully merged (or explicitly merged without --auto) before dispatching slices.
| gh pr merge "$MERGE_BASELINE_PR" --repo "$REPO" --squash --auto || true | |
| gh pr merge "$MERGE_BASELINE_PR" --repo "$REPO" --squash |
|
@copilot apply changes based on the comments in this thread |
- run_repo_architect_slices.sh: remove unused python3 dep check, add --branch filter to wait_for_new_run_id and BEFORE_RUN_ID snapshot, fail hard on artifact download failure and missing latest_analysis.json, hard-fail on mode mismatch, remove --auto/||true from MERGE_BASELINE_PR - bootstrap_repo_architect_slices.sh: replace embedded heredocs with cp from tracked canonical paths (eliminates drift risk) - repo_architect.py: add lane/targets to Config; read REPO_ARCHITECT_LANE and REPO_ARCHITECT_TARGETS env vars in build_config(); add _apply_lane_filter() to scope analysis to declared targets; route build_patch_plan() by lane prefix so lane/targets are semantically real Co-authored-by: Steake <530040+Steake@users.noreply.github.com>
All six review comments addressed in commit
|
|
@copilot Rework PR #7 on top of current main after PR #8 is merged. Keep PR #8’s hardening intact. Then fix the two orchestration defects called out in review:
|
|
…x both orchestration defects - Restore repo_architect.py and repo-architect.yml to exact main state (PR #8 hardening fully intact; PR #7's superseded lane/targets additions removed) - Rewrite run_repo_architect_slices.sh for PR #8 workflow interface: dispatch with mode + lanes (not lane/targets/allow_dirty which no longer exist) - Slice sequence: report → parse_errors → import_cycles → entrypoint_consolidation → hygiene → campaign - Fix wait_for_new_run_id: filter by --event workflow_dispatch + --branch, record DISPATCH_TIME before dispatch, jq-filter createdAt >= dispatch_time so pre-existing and cross-branch runs are excluded; pipe to jq separately so --arg is correctly resolved (gh -q does not forward jq flags) - Fix MERGE_BASELINE_PR: explicit squash merge, fail fast on merge error, poll gh pr view until state=MERGED before dispatching any slices Co-authored-by: Steake <530040+Steake@users.noreply.github.com>
Done in commit Rebased on main (PR #8 intact):
Fix 1 —
Fix 2 —
Same fix as above ( Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
Description
Adds a repeatable, automated "fat slices" execution path that dispatches
repo_architect.pyas a sequence of scoped GitHub Actions runs — report and mutate-by-lane slices — with zero manual editing between runs. Rebased on top of main (post-PR #8) to keep all lane scoping, model fallback, campaign mode, and entrypoint consolidation hardening intact.Workflow —
.github/workflows/repo-architect.ymlNo changes from main (PR #8). The workflow inputs (
mode,lanes,max_slices,github_model,mutation_budget) and theREPO_ARCHITECT_BRANCH_SUFFIX/ model-fallback env vars are fully preserved as merged.Orchestration script —
scripts/run_repo_architect_slices.shgh run watch --exit-statusbefore proceedingmode+lanesfields; the obsoletelane,targets, andallow_dirtyfields are removedDISPATCH_TIME(UTC ISO-8601) immediately beforegh workflow run; filtersgh run listby--event workflow_dispatch --branch "$BRANCH"; pipes JSON tojq --arg ts "$DISPATCH_TIME" 'select(.createdAt >= $ts)'— pre-existing in-flight runs and runs on other branches (e.g. scheduled triggers) cannot be picked upGH_API_DELAYenv var (default5s) controls post-dispatch polling delaylatest_analysis.jsonterminate the slice with a non-zero exit; mode mismatch is a hard error.agent/latest_analysis.json— printsmode,status,architecture_score,changed_files, andpr_urlMERGE_BASELINE_PR— synchronous, confirmed merge: explicitgh pr merge --squash(no--auto, no|| true); pollsgh pr view --json stateuntilstate == MERGEDbefore dispatching any slice — guarantees all slices run against the fully merged baselineSlice sequence:
reportreportparse_errorsmutateparse_errorsimport_cyclesmutateimport_cyclesentrypoint_consolidationmutateentrypoint_consolidationhygienemutatehygienecampaigncampaignBootstrap script —
scripts/bootstrap_repo_architect_slices.shValidates that the workflow and runner script are present at their canonical tracked paths and marks the runner executable. Does not embed or overwrite file contents — the committed files are the single source of truth, eliminating any risk of heredoc drift.
Related Issues
Test Evidence
bash -nsyntax validation passes on both shell scriptspython -c "import yaml; yaml.safe_load(...)"python -c "import ast; ast.parse(...)"confirms no Python syntax errors inrepo_architect.pytests/test_repo_architect.pytests pass against the restoredrepo_architect.pyjq --argpattern validated: piped invocation correctly filters runs bycreatedAt >= DISPATCH_TIMEChecklist
pytest tests/)black .andisort .)Original prompt
📱 Kick off Copilot coding agent tasks wherever you are with GitHub Mobile, available on iOS and Android.