Skip to content

fix(bonedigger-report): derive booted image name from live bootc status - #1127

Open
kubestellar-hive[bot] wants to merge 3 commits into
mainfrom
scanner/fix-bonedigger-report-image-name
Open

kubestellar-hive[bot] wants to merge 3 commits into
mainfrom
scanner/fix-bonedigger-report-image-name

Conversation

@kubestellar-hive

Copy link
Copy Markdown
Contributor

Fix

system_files/bluefin/usr/libexec/bonedigger-report's read_boot_status() already corrected IMAGE_TAG and IMAGE_REF from the live bootc status booted ref, but left IMAGE_NAME sourced only from the build-time image-info.json. After a rebase (e.g. bluefin -> dakota) that name goes stale, so route_issue_repo() kept routing ujust report to the pre-rebase repo.

This derives IMAGE_NAME from the booted ref's repository basename (same jq / /run/ublue-os/booted-image fallback chain already used for tag/ref), and adds BATS coverage for a rebased deployment.

Closes #1009


Filed by scanner agent (ACMM L5 — hold-gated mode). Hold-gated: human review required.

— hive: agent=scanner backend=copilot

…bootc status

image-info.json's image-name field is baked at build time and goes stale
after a bootc rebase (e.g. bluefin -> dakota). read_boot_status() already
corrected IMAGE_TAG and IMAGE_REF from the live booted ref but left
IMAGE_NAME untouched, so route_issue_repo() still routed rebased hosts'
reports to the pre-rebase repo.

Derive IMAGE_NAME from the booted ref's repository basename, with the
same jq/booted-image-snapshot fallback chain already used for tag/ref.
Add BATS coverage exercising a rebased bluefin->dakota deployment.

Closes #1009

Signed-off-by: scanner <scanner@users.noreply.github.com>
@kubestellar-hive kubestellar-hive Bot added the hold Work is intentionally paused. label Sep 16, 2026
@kubestellar-hive kubestellar-hive Bot added hold Work is intentionally paused. agent/scanner Filed or owned by the scanner agent. hive/hosted-projectbluefin-knuckle-gjvq Routed by the hosted Project Bluefin Hive deployment. labels Sep 16, 2026
clubanderson pushed a commit to hivecommons/hive that referenced this pull request Sep 16, 2026
Hive agents work on repositories other than hive's own, and those
repositories state their local rules in AGENTS.md — the cross-tool
convention hive already reads and injects. Nothing told the agent which
side wins a conflict, and hive's wording was the more forceful of the two
every time, so the repository lost every conflict.

InjectionText rendered the repo's rules under a bare header as
undifferentiated prose. Hive stated the same subjects as imperatives with a
verification step attached — "confirm the PR's base is that branch before
you report done". Given a document that says one thing and an imperative
that says another, a model follows the imperative, consistently.

projectbluefin/bluefin's AGENTS.md says "All pull requests target
`testing`. Never open a content PR against `main`"; hive agents opened
#1275 and #1276 against main and failed its base-branch gate.
projectbluefin/common#1127 and projectbluefin/review#597 died on
conventional-commit title gates against hive's hardcoded "[<lane>] …" PR
titles. Four dead-on-arrival PRs in one night, none of them a model error —
the agents did precisely what hive instructed.

Three changes, in the order they matter:

State precedence in the injection. The block now leads with a declaration
that the repository's instructions outrank hive's defaults on any conflict
— the branch a PR targets, the title format, commit conventions, the test
command, review etiquette. Two carve-outs are not the repository's to
override: hive's safety and authorization rules (never merge your own PR,
never bypass a write gate or the hive-open-pr path, never act as another
agent), and an instruction the assignment names explicitly for that one
task. An empty AGENTS.md still injects nothing at all, so the statement
never appears with no rules under it.

Stop asserting repo facts in the defaults. A precedence rule that has to
fight hive's own confident wording on every kick is a rule that loses some
of the time. The contributor task prompt's fallback wording now says to use
the base the repository requires — checking its AGENTS.md, CONTRIBUTING and
PR template, since a repo on a promotion model takes PRs on an integration
branch rather than on its released default — and to fall back to the
default branch only when nothing names one. #5729's verification step
survives, pointed at the repository's requirement instead of hive's guess;
so does the load-bearing "do not use the branch you find" clause. #4928 and
#6081 were this same assumption at earlier stages, and each fix replaced
one wrong assertion with a better one; the remaining gap was asserting at
all. The prompt also now tells the agent to read the repo's AGENTS.md
itself, because the contributor path never calls primeAgentsMd — on that
path the repo's rules are not outranked, they are absent.

Drop the hardcoded PR title. 16 policy templates per tree prescribed
--title "[<lane>] …", hive's own house style projected onto every repo it
touches. They now take the title from the target repository and pass --base
explicitly. The [<lane>] prefix is unchanged where it is load-bearing —
ISSUE titles, which classify.classifyLane routes by prefix — and it was
never load-bearing for PRs: intent.Classify keys off AgentAuthor, changed
paths and FeatureSignals, never the title. github.ClassifyReviewClass does
read PR-title prefixes, but only to order a review queue it documents as
presentational, it falls back to agent/<lane> labels, and it matches the
conventional-commit word in the same pass — so the titles here keep
classifying via "fix:"/"docs:"/"refactor:"/"planning:". quality's PR title
had no such word, so it becomes "test: …" rather than losing its class.

Both policy trees are edited together, byte-identical, as
TestEmbeddedDefaultsMatchPolicySource requires.

Closes #7159

Signed-off-by: Danathar <Danathar@users.noreply.github.com>

@hanthor hanthor 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.

The defect you're describing is real, and this is the right place to fix it. read_image_info() sets all four fields from the build-time image-info.json, and read_boot_status() was already correcting IMAGE_REF and IMAGE_TAG from the live booted ref while leaving IMAGE_NAME alone — an inconsistency that's easy to miss on a read-through. Since route_issue_repo() passes exactly "$IMAGE_NAME" "$IMAGE_TAG" to ublue-image-repo, half-corrected inputs really do route a rebased deployment's ujust report at the pre-rebase repo. Reusing the existing jq / /run/ublue-os/booted-image chain rather than adding a second source of truth is the right call, and the new test is a genuine test — I confirmed the suite goes 19 → 20 with no regressions:

$ bats tests/test_bonedigger_report.bats   # merge-base fbbb193
ok 19 help intent does not collect diagnostics or create an issue
$ bats tests/test_bonedigger_report.bats   # this head
ok 20 help intent does not collect diagnostics or create an issue
ok=20 fail=0

and it kills the mutants that matter most. Removing the IMAGE_NAME="$booted_name" assignment, changing ${booted_repo##*/} to ${booted_repo%%/*}, and changing ${booted_repo%%:*} to ${booted_repo##*:} each fail test 4. That's real coverage, not a smoke test.

One correctness problem, though, and it's in the parsing order.

The tag is stripped before the basename is taken:

local booted_repo="${booted_ref%%@*}"
booted_repo="${booted_repo%%:*}"      # strips from the FIRST colon
local booted_name="${booted_repo##*/}"

%%:* cuts at the first colon in the whole reference, but in an OCI reference the first colon can belong to a registry port rather than the tag. The basename then falls out of the registry host:

$ for ref in "ghcr.io/projectbluefin/dakota:stable" "ghcr.io/projectbluefin/dakota@sha256:dead" \
             "localhost:5000/bluefin:latest" "registry.example.com:5000/projectbluefin/dakota:stable"; do
    booted_repo="${ref%%@*}"; booted_repo="${booted_repo%%:*}"; pr="${booted_repo##*/}"
    c="${ref%%@*}"; c="${c##*/}"; c="${c%%:*}"
    printf "%-52s PR=%-22s CORRECT=%s\n" "$ref" "$pr" "$c"
  done
ghcr.io/projectbluefin/dakota:stable                 PR=dakota                 CORRECT=dakota
ghcr.io/projectbluefin/dakota@sha256:dead            PR=dakota                 CORRECT=dakota
localhost:5000/bluefin:latest                        PR=localhost              CORRECT=bluefin
registry.example.com:5000/projectbluefin/dakota:stable PR=registry.example.com CORRECT=dakota

IMAGE_NAME becomes localhost or registry.example.com, which is strictly worse than the stale-but-plausible build-time name it replaces — ublue-image-repo will fall through to the projectbluefin/common default for a deployment it could otherwise have routed. The surrounding comment (and dakota#1328, cited two lines up) calls out "rebased or locally built deployments" specifically, and a local registry on a port is the ordinary way people produce those, so this is squarely inside the case the change is aimed at. Note the existing tag extraction two lines above already uses last-colon semantics (${booted_ref##*:}) for the same reason.

Taking the basename first makes the colon unambiguous, because a tag is the only colon that can appear in the final path component:

local booted_repo="${booted_ref%%@*}"
local booted_name="${booted_repo##*/}"
booted_name="${booted_name%%:*}"

That's equivalent on every ref your test exercises and correct on the port cases too.

Second, smaller: the digest-stripping line is unverified. I deleted it —

-            local booted_repo="${booted_ref%%@*}"
+            local booted_repo="$booted_ref"

— and the suite stayed green:

$ bats tests/test_bonedigger_report.bats | grep -c '^not ok'
0

With that mutation a digest-pinned deployment yields IMAGE_NAME="dakota@sha256". The code is right as written; nothing proves it stays right. Digest-pinned refs are routine for bootc (bootc switch --digest, pinned rollbacks), and the case statement immediately above this block exists precisely because of them, so the gap is worth closing. Two cases added alongside test 4 cover both points — one with a …@sha256:… booted image, one with a localhost:5000/…:latest booted image asserting IMAGE_NAME is bluefin and not localhost.

mergeable_state is blocked. Everything here is a handful of lines in one function plus two test cases; happy to re-review quickly once they're in.


Generated by Claude Code

@kubestellar-hive kubestellar-hive Bot changed the title [scanner] fix(bonedigger-report): derive booted image name from live bootc status fix(bonedigger-report): derive booted image name from live bootc status Sep 17, 2026
`${booted_repo%%:*}` cut at the first colon of the whole reference, so a
registry port was mistaken for a tag: `localhost:5000/bluefin:latest`
yielded `IMAGE_NAME=localhost`. Take the basename first, then strip the
tag — in the final path component a colon can only be a tag.

Adds two regression cases: a digest-pinned booted ref (which also pins
the previously unverified `%%@*` digest strip) and a port-bearing
registry ref.

Assisted-by: Claude Opus 4.6 via GitHub Copilot
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@castrojo
castrojo requested review from a team and repires as code owners September 19, 2026 13:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent/scanner Filed or owned by the scanner agent. hive/hosted-projectbluefin-knuckle-gjvq Routed by the hosted Project Bluefin Hive deployment. hold Work is intentionally paused.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[scanner] bonedigger report routes rebased hosts using stale image metadata

3 participants