Skip to content

Serve footer logos from the published brand assets and keep legacy URLs migratable - #124

Merged
CompleteDotTech merged 70 commits into
mainfrom
issue/47
Nov 1, 2026
Merged

CompleteDotTech merged 70 commits into
mainfrom
issue/47

Conversation

@CompleteDotTech

@CompleteDotTech CompleteDotTech commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Change and affected skills

Resolves #47
Resolves #48
Resolves #49
Resolves #50

footer --check --online failed because both footer logo URLs pointed at CompleteTech-LLC/.github/main/brand/, which returns 404. The footer now points at the logo masters published in this repository (assets/brand/logo.png and logo-dark.png on main, HTTP 200 with the expected hashes), and the former URLs stay in footer.legacy_logo_urls so existing READMEs still migrate safely.

  • Brand data (references/brand.yaml, brand.schema.json, brand.lock.json regenerated through the CLI): the published URLs plus legacy_logo_urls, which also lists the historical company-website logo URL. All brand URLs and hosts live in brand.yaml; no brand path is hardcoded in Python.
  • Footer recognition and upgrade safety (scripts/ctshowcase/readme.py, scripts/showcase.py): upgrade() replaces an old footer only for a demonstrated historical logo (a configured legacy_logo_urls entry matched on parsed src/srcset URLs, or the conventional local docs/images/logo.svg) together with the strong footer signature. Alt text alone is never provenance. Images are classified from whole parsed attributes (exact names, first occurrence wins, including valueless first attributes), so data-alt, title text, spoofed hosts, userinfo and unexpected ports never count. Authored partner and foreign images, authored anchors and the generated banner's link wrapper are preserved; a change that would lose one is flagged by the preservation guard and the CLI refuses the write. readme --bootstrap --write refuses to regenerate a marked footer that holds an authored image in EVERY bootstrap state (none, pristine and edited: it fails with readme-shrink and leaves the README byte-unchanged), and the G/H unmarked website-logo and docs/images/logo.svg footers now migrate. The two existing legacy-footer tests are unchanged.
  • CI (.github/workflows/footer-assets.yml, job footer-online): pull requests run the OFFLINE step that the configured logo files exist in the checkout under assets/brand/. The real footer --check README.md --online HEAD runs on push to main (footer-related paths), on the weekly schedule and on manual dispatch, with contents: read only. This matches issue footer --check --online fails: both footer logo URLs return 404 #47 ("a scheduled check or CI step fails when they do not") and E2.4.3 Add a CI check with an offline-friendly mock #50 ("offline-friendly mock", "real HEAD on a schedule", mocked unit tests for the gate logic); the online step has not yet run in hosted CI and is first exercised after merge (a manual dispatch will confirm).
  • Docs: references/decisions.md keeps decision 18's quoted markup verbatim and explains the configured URLs in a separate, clearly labelled skill-maintenance note; references/readme-variants.md (the upgrade row now says a logo qualifies by its parsed src/srcset or the local docs/images/logo.svg, never by alt alone), references/art-direction.md, the changelog, examples and assets/brand/README.md describe the published URLs and the actual CI behaviour. No brand mark was created or redrawn.
  • Tests: tests/test_footer_public_assets.py (offline mock of the published assets), tests/test_footer.py, tests/test_footer_fenced_example_migration.py, tests/test_footer_upgrade_preservation.py and attribute-token tests cover the partner, foreign, spoof, valueless-attribute, banner-wrapper, bootstrap and G/H cases; synthetic fixtures only.

Prior work

Searched this repository's PRs and issues for the footer logo URL problem (search repeated before this refresh):

Provenance

Commits dfc93ed03acf4d23c187c33ada1ebfbf4fe70dbc and 5a3d78d8de9e0eac7f59d3e70b8ff5a5873a0373 are inherited, already-published history that predates the current remediation. They carry generic Co-Authored-By: Claude trailers; no more specific model is claimed for them because no native evidence is available.

Three already-published merge commits in this branch have no Co-Authored-By trailer. Commit metadata is immutable once published and the user's instruction forbids force-push, so these are recorded as provenance exceptions, not defects fixed by changing source:

Merge commit What it merges Made by (native evidence)
366c735c994f361c13a6259e36ef1c67d47297eb hk/47-r3 decisions.md skill note (Haiku commit d5c63ca, Haiku trailer) Sonnet owner integration fix:#47:r3, native agent a755d4e54043aaf95, runtime model claude-sonnet-5-5
76ee8b61fe4323f8da22e8eff470c9c5d37694ac hk/47-r3 README footer replacement fix (Haiku commit 740303d, Haiku trailer) same Sonnet owner integration fix:#47:r3, a755d4e54043aaf95, claude-sonnet-5-5
7fc3743b951173e02fc447a5d32f5fa409d2654d 849f67e (Haiku commit, Haiku trailer) Sonnet owner integration fix:#47:r2, native agent a5f0db6ef29599f82, runtime model claude-sonnet-5-5

Nothing is rewritten, no trailer is claimed that does not exist, and no model beyond the native evidence is asserted. From here on, every commit and merge commit carries the verified trailer of the role that made it before it is published (Haiku 5.5 for file workers, Sonnet 5.5 for owner commits and merges). This is a provenance record only; it is not an approval of the code.

Additional integration merges without a trailer (the model trailer on merge commits is a convention of the orchestration prompt, not a repository rule; recorded, not rewritten, no attribution invented):

Merge commit Adopts Made by (native evidence)
cad87ddf1662e5f3c5088217255fce891ec1922f Haiku commit c017dd14e3e318e6ac700b3653f8eaeb17e05417 (decisions.md wording) Sonnet owner integration fix:#47:r5, native agent a7a484513792f76f1, claude-sonnet-5-5
512f13e4b707c7c6e6b2a14fdde56362bd9dad52 Haiku commit 2b0e0b0723b96429a39ff750e20aae66003304b8 (art-direction.md) same Sonnet owner integration a7a484513792f76f1, claude-sonnet-5-5

Further integration merges without a trailer (convention of the orchestration prompt, not a repository rule; recorded, not rewritten): 9a5ae0d (adopts Haiku d4d4c0b, claude-haiku-5-5) and the e58465e/97b775d line, made by the Sonnet owner integrations fix:#47:r0 (native agent a6f7eade5) and fix:#47:r1 (native agent afefb0a7e), both claude-sonnet-5-5; the Haiku source commits carry Haiku 5.5 trailers.

Later history on this branch, recorded as it happened (nothing rewritten): commit 384f443 briefly changed the CI workflow to run the online HEAD on pull requests, which contradicts the real acceptance of #47/#50; 0f1eec8 restored the workflow and its original test byte-for-byte (verified against bec6391), and 76f0108 removed a duplicate test helper flagged by Ruff F811; d17909e extended the bootstrap refusal to the none and pristine states; 7a72de1 corrected the readme-variants logo wording, pinned the CI policy in a test and normalized one new test file to LF. The merge commits after the table above follow the same convention (integration merges by the Sonnet owner, Haiku source commits carry Haiku 5.5 trailers); this section is a provenance record, not an approval.

Evidence (exact head 7a72de1c706a6f5ee815aa28d7589c90620ad13b, base main 85f12d8198f77a1bea150a9b0afff0125af9e990 integrated by a normal merge)

  • Isolated VM (Ubuntu 24.04, run by the outer coordinator; receipt vm-7a72de1c706a6f5ee815aa28d7589c90620ad13b-result.json): package tests, package validator, full pytest and quality validator passed; pytest 1198 passed, 11 skipped, 37 subtests. The skips are the pre-existing absent external fixtures; the Windows-only symlink cases run in Linux; no jsonschema or changed-feature skip.
  • Footer probes on the same VM: seven footer probe groups, the r7 same-host-photo and anchor controls, bootstrap and G/H cases, all three bootstrap states (none, pristine, edited: each refuses the write and keeps the authored partner bytes), and fresh public logos (HTTP 200, downloaded sha256 equals the committed masters: logo.png 243500 bytes a5c3c4ef...1621, logo-dark.png 210785 bytes 0dc00c0e...7ec) all pass. A deliberately missing asset fails with fail:offline (negative control).
  • Hosted CI on this head: validate-package (ubuntu, windows, macos), pytest (ubuntu, windows, macos), validate and footer-online all completed with success (15 check runs, push and pull-request matrices). One macOS validate-package job was left by GitHub in an inconsistent state (status in_progress with conclusion success while its workflow run was completed); it was rerun as a targeted job rerun, the original record is preserved, and the rerun completed with success.
  • Local Windows run at this head (supplemental, guarded single full run): 1196 passed, 13 skipped, 37 subtests (the two extra skips are the Windows symlink-privilege skips that run in the VM). Earlier local Windows runs on other heads failed at fixture git commit setup in the local signing environment; those logs are preserved and are not evidence for this head.
  • Independent reviews of this exact head and base (native provenance verified): two Opus reviewers (claude-opus-5-5) and Codex gpt-6.1-sol at max effort each returned an explicit approve with zero findings. An earlier Sol review of this head returned incomplete (it had no network and the live HTTP receipts were not in its context); the receipts are now supplied inline and the incomplete record is kept. Earlier reviews of older heads (including a lifecycle-only request for explicit closing keywords, resolved by the keywords above) do not carry over.
  • Not run: mmdc/Mermaid rendering (tool unavailable); private deny-list check (no private fixtures); pyright (no config).

Limitations

  • The real online HEAD step has not run in hosted CI yet because pull requests run only the offline file-existence step; its first run is on push to main, the weekly schedule or a manual dispatch (to be triggered after merge).
  • Non-blocking reviewer suggestions tracked for later cleanup: an unreachable second authored-footer refusal in the bootstrap edited branch, broader path filters for footer-assets.yml (scripts/ctshowcase/readme.py, references/brand.lock.json), a clearer error if a logo URL is ever off main, and narrowing the historical bare local logo forms. A follow-up issue will cover readme --mode header, which still regenerates a marked footer without the authored-content refusal (pre-existing, outside this change).

Boundaries

Activation keys, consent, approval gates and specialist entry points are unchanged. Branding decisions are not altered beyond repairing the unreachable URLs (the quoted decision text is untouched). No registry release, visibility change or live external action is implied. Shared validators (scripts/validate_package.py, tests/test_package_contract.py) are byte-identical to main.

Family consistency

Single-repository change; no sibling skill PRs are affected.

🤖 Generated with Claude Code

CompleteDotTech and others added 2 commits October 31, 2026 12:30
Retain recognized legacy footer URLs for safe README migration.

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review Summary

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

Review Status Commit Review trigger
🔒 Security Review ⚠️ Failed 2026-10-31T19:07:28.719453Z
We couldn’t complete this review. Comment @codex security review to try again.
5a3d78d 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.

@chatgpt-codex-connector

Copy link
Copy Markdown

The account paying for this security review has reached its Codex usage limits. The payer can check the Codex usage dashboard. For personal accounts, using credits requires enabling “Use credits for security reviews” in Code review settings. If you do not manage the paying account, contact this repository's admins.

CompleteDotTech and others added 26 commits October 31, 2026 15:17
Adds a weekly and manual workflow that runs
'python scripts/showcase.py footer --check README.md --online' so a
dead footer logo URL fails CI. Part of #47 (subissue #50).

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
…ooter images

- callout_only (variants G and H) now replaces a recognized old footer, marked
  or unmarked, and reports the replaced lines to the preservation check.
- is_footer_copy requires every src/srcset to be a footer logo URL; a matching
  alt no longer vouches for a custom image.
- decisions.md: drop the unsupported user-request attribution, add a neutral
  note outside the verbatim excerpt.
- Tests for G/H marked and unmarked legacy footers, the guard, the scheduled
  workflow and the deliberately legacy template fixture.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Old footers that reference assets/logo.png (and the other former local
logo names) are a footer copy again when the image alt is exactly the
company or the footer alt. Published URLs still must be footer logo URLs,
and any other src keeps the image from counting as a footer copy.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
… URLs

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… makes footer check report drift

callout_only now tracks whether a recognized footer was removed (marked loop or drop_old_footer) and appends the replacement in that case, even when footermod.check reports fail:drift because of footer-like text inside a fenced example.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Label the decision 18 logo-URL repair as a skill amendment pending user
confirmation, move the repair paragraph out of the quoted decision text,
and neutralize the line-5 note and file preamble.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
…fenced-example and decisions provenance tests

- footer-assets.yml: add push to main with the same paths filter; on pull_request check the configured
  footer logo paths exist in the PR checkout; the online HEAD runs only off pull_request.
- tests: G/H regression for a fenced footer-like example plus a marked legacy footer; workflow trigger test.
- validate_quality.py: gate_decisions_provenance (decisions.md line 3 not fully verbatim; skill note outside quote).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Remove gate_decisions_provenance and its call in main(). It hard-coded
decisions.md line numbers and exact English sentences, so harmless document
reorganisation would fail it. It sits outside the behavioural footer repair.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The Brand files row named the former CompleteTech-LLC/.github/brand/
location, which returns 404. Name the published masters in
assets/brand/ (the copies the generators and footer use), keep the
former location as historical only, and note the matching sha256 for
the logo pair.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
…air (#47)

Restore the decision 18 exact markup to the origin/main text and keep the
current footer URLs only in the labelled skill note. Remove the requester,
date and confirmation wording the repair notes carried.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
…nize picture local logos, report only changed footer lines as removed (#47)

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

Adds tests/test_footer_upgrade_preservation.py. Partner, foreign and look-alike
host images carrying the company alt must survive readme.upgrade with no removed
allowance; the demonstrated own-site legacy logos (the company website host
derived from brand data, and docs/images/logo.svg) still migrate. Helper tests
use the own_site flag from the agreed interface. Against e58465e the partner,
foreign and derived-host negatives and the own_site helper tests fail; they
reproduce the upgrade() loose_src deletion for the readme.py fix to address.
The write-flow test is omitted: no cheap public entry point exists (see module
comment).

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
…never alt-only trust (#47)

Replace loose_src=True in upgrade() with own_site=True: under a company alt only
the brand website host (brand_strings.website) and docs/images/logo.svg migrate;
partner, foreign and look-alike images stay authored. loose_src stays an opt-in helper kwarg.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
CompleteDotTech and others added 26 commits October 31, 2026 20:20
…ce semantics (#47)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…footer lines (#47)

- _own_site_logo accepts only the exact OWN_SITE_LOGO_PATHS on the configured
  company website host, so other files on that host stay authored content.
- upgrade() shares one multiset of re-emitted footer lines across the marked
  and unmarked branches; unmarked old-footer lines the new footer carries
  again are no longer reported as removed (_unreemitted).

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
…footer lines (#47)

Adds tests/test_footer_r7_regressions.py. Same-host non-logo images must survive upgrade,
a historical logo path with a query still migrates, a regular unmarked footer must not
hide lost banner anchors, and removed must not include re-emitted footer lines. The
new tests that depend on the readme.py fix fail at 020f30a as expected; no existing
test is changed.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
…y footer; docs: own-site logo paths (#47)

The anchor regression now fails if the whole old footer is exempted again
(verified by reverting to 'removed += old_footer'). CHANGELOG and
readme-variants describe OWN_SITE_LOGO_PATHS recognition and the
multiset-limited removed report.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…urls (#47)

Remove the hardcoded OWN_SITE_LOGO_PATHS from Python; the website logo URL is brand data in references/brand.yaml (lock refreshed via config --write-lock).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…hored images

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
…igration (#47)

callout_only called drop_old_footer without own_site=True, so an unmarked
trailing footer using footer.legacy_logo_urls or docs/images/logo.svg was
rejected for G/H forks and archived repos. Match upgrade(). Marked footers
stay strict, as in upgrade().

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
…ssions; drop stale OWN_SITE_LOGO_PATHS wording (#47)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
footer-online now runs footer --check README.md --online on pull_request, push, schedule and workflow_dispatch (contents: read, no continue-on-error); the PR-only local-file step stays as extra coverage. The refreshed acceptance overrides the older r2-authoritative-ci-criteria adjudication on PR online checks, so the renamed regression is a deliberate change, not a weakening.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…line-on-PR docs claims (#47)

Reverts the invented online-HEAD-on-pull-request gate from 384f443 per the
binding adjudications (issue #47/#50 acceptance: scheduled check or CI step,
offline-friendly mock). Restores footer-assets.yml and the footer migration
test to bec6391 content; docs state that pull requests run the offline
file-existence step and the online HEAD runs on push to main, weekly and
manual dispatch. Bootstrap-refusal, G/H own-site and legacy_logo_urls
wording fixes are kept.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
tests/test_footer_upgrade_preservation.py defined gh_ctx twice (lines 253
and 343), failing ruff F811 in validate_quality. Both bodies were identical,
so the second definition with its duplicate GH_VARIANTS, PARENT and UPSTREAM
constants is removed. The G/H tests now use the shared GH_UPSTREAM constant.
No test function, parametrization or assertion changed.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The authored-footer safeguard only ran for an edited template body. A
pristine or unmarked (none) README reached header_only(), which replaced
the marked footer and silently deleted a partner or foreign image.

Move the check into _authored_footer_refusal() and run it on the original
text before dispatching on bootstrap_state(), so every state refuses before
writing. The edited-branch guard reuses the same helper with its existing
problem text and preservation details.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
…bootstrap states (#47)

Add CLI-level regression tests for `readme --bootstrap --write` where the marked footer
holds an authored partner or foreign image (https://example.test/partner-badge.png and
assets/partner.png) in the pristine and none states. They expect a readme-shrink refusal
with README.md byte-identical; against the unfixed showcase.py they fail (the write
succeeds and the partner image is replaced), which reproduces the P1 finding.

Positive controls: an own-site legacy footer still migrates to the current brand logo in
both states, and a current footer is idempotent across two runs.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
…rap (#47)

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

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

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Line 255 (upgrade row) no longer lets a matching company alt qualify a
footer logo image. Qualifying URLs are the brand footer logo URL, a
footer.legacy_logo_urls entry, or docs/images/logo.svg under the company
alt; alt alone never qualifies.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
test_scheduled_workflow_really_heads_the_footer_logos now asserts that the
online HEAD step is guarded by `if: github.event_name != 'pull_request'`,
that a pull_request trigger exists, and that the offline file-exists step
is pull_request-only. Test-only change; no existing assertion is weakened.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant