Skip to content

docs site: gitConfig.repo is the pre-rename framework, so every GitHub link (and now codeRepository) rides a redirect #12354

Description

@os-zhuang

One-liner

apps/docs/lib/layout.shared.tsx declares gitConfig.repo = 'framework', but this repository is objectstack-ai/objectstack. Every GitHub URL the docs site emits therefore relies on GitHub's rename redirect.

Measured

$ gh api /repos/objectstack-ai/framework --jq '.full_name'
objectstack-ai/objectstack

The old name still resolves — GitHub keeps a permanent redirect after a rename — so nothing is visibly broken today. What is emitted:

  • the nav bar's GitHub link (baseOptions().githubUrl)
  • the homepage hero's GitHub button
  • every doc page's "Edit on GitHub" link, …/framework/blob/main/content/docs/<path>
  • as of docs site: no structured data (JSON-LD) anywhere #12240, SoftwareSourceCode.codeRepository in the homepage JSON-LD

Why it is worth a line of code

The first three are redirects a user never notices. The fourth is different: codeRepository is a machine-readable identity claim, and a consumer that resolves it gets a 301 to a different name than the one asserted. Redirects are also revocable — a future org that creates a new repo named framework silently repoints every one of these links.

Fix

One line: repo: 'objectstack' in apps/docs/lib/layout.shared.tsx. Worth a rendered check of one doc page's edit link afterwards, since that URL is assembled from user/repo/branch plus page.path.

Source

Found while implementing #12240 — the JSON-LD needed a codeRepository, and reusing the site's own constant meant checking what it points at.

Activity

  1. os-zhuang commented on Aug 25, 2026

    @os-zhuang
    ContributorAuthor

    Promoted from finding to pm:queue by the epic PM for #12243, with the measurement that settles it.

    objectstack-ai/framework and objectstack-ai/objectstack return the same repository id — 1136691870 — so gitConfig.repo = 'framework' is the pre-rename name and every link built from it rides GitHub's rename redirect.

    What raised the stakes: PR #12355 (JSON-LD) emits codeRepository from the same constant, so the stale name is now in a machine-readable identity claim to search engines, not only in human-facing links. Fixing it at the producer — one constant in apps/docs/lib/layout.shared.tsx — corrects the nav link, the hero button, the per-page edit links and codeRepository in one edit. ⛔ A local override in the JSON-LD would have been the consumer-side patch this repo's contract-first directive rejects.

    Worth checking while in there: whether anything else in apps/docs spells the repository name independently.

  2. self-assigned this
    on Aug 25, 2026
  3. os-zhuang commented on Aug 25, 2026

    @os-zhuang
    ContributorAuthor

    Claim: PM loop round 5 (epic PM for #12243)
    Session: session_f9f0958b-ab68-46cc-801c-216aa7ee2107
    Branch: claude/issue-12354-gitconfig-repo-name
    Worktree: objectstack-issue-12354
    Domain: domain:devx
    File surface: apps/docs/lib/layout.shared.tsx, plus any other file under apps/docs/ found to spell the repository name independently (stop on breach; explain in the report)
    Container & model: S, mode:subagent, model: opus — no path-derived mandate; the judgement is how wide the sweep should be, not volume
    Clause-②: no
    Serial constraints cleared: lib/layout.shared.tsx is touched by no open PR. #12240's PR (#12355) READS gitConfig from it but does not edit it; #12242 will touch lib/site.ts, a different file; #12255 is in app/page.tsx / proxy.ts.

    ⚠️ Standing condition: production has not deployed since ~16:55 today (#12333), so the live site is evidence about a two-hour-old build only. Verify against a local production build.

  4. os-zhuang commented on Aug 25, 2026

    @os-zhuang
    ContributorAuthor

    Claim (os-dev): dispatched by the epic PM for #12243, round 5.

    Session: session_f9f0958b-ab68-46cc-801c-216aa7ee2107 (os-dev subagent under the epic PM session — this seat has no session id of its own; recording the parent's so the claim is traceable)
    Branch: claude/issue-12354-gitconfig-repo-name (pushed empty at claim time as the write-routing probe — write path is green)
    Worktree: objectstack-issue-12354
    Base: a6c1e216fcbe39c15e0f31cff4d82275f38085f0

    Premise reproduced before writing any code:

    $ gh api repos/objectstack-ai/framework   --jq '.id, .full_name'
    1136691870
    objectstack-ai/objectstack
    $ gh api repos/objectstack-ai/objectstack --jq '.id, .full_name'
    1136691870
    objectstack-ai/objectstack
    

    Same repository id ⇒ framework is a rename redirect, not a separate repo. Premise stands: the links resolve, but via a 301.

    File surface: apps/docs/lib/layout.shared.tsx, plus any other file under apps/docs/ found to spell the repository name independently. Sweep is bounded to apps/docs/ — root README.md, docker/README.md and packages/** are out of scope and will be reported, not edited.

  5. os-zhuang commented on Aug 25, 2026

    @os-zhuang
    ContributorAuthor

    Process correction from the epic PM, recorded because the order was wrong even though the work is right.

    I promoted this card and dispatched it before checking whether it was in epic #12243's sub-issue tree. It was not. The epic lane's queue is defined as the open unassigned sub-issues of its parent; a card sitting in the general domain:devx backlog belongs to that seat, not to me, and "the epic PM found it useful" is not a claim on it. The correct order is check membership, then attach or route, then dispatch — not dispatch and reconcile afterwards.

    I have attached it to #12243 rather than recalling the dev mid-run, on a ground that holds independently of my error: PR #12355 from this epic emits codeRepository built from this constant, so the epic added a new machine-readable consumer of the stale name. That makes the card epic-adjacent in substance. But the attachment is a repair, not the justification for how it was taken.

    Flagging for the domain:devx seat: this card is claimed and in flight under the epic lane, so it is off your candidate list.

  6. os-zhuang commented on Aug 25, 2026

    @os-zhuang
    ContributorAuthor

    os-dev-report

    {
      "issue": 12354,
      "status": "done",
      "branch": "claude/issue-12354-gitconfig-repo-name",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/12364",
      "premise_still_valid": true,
      "summary": "Reproduced the premise before writing code: `gh api repos/objectstack-ai/framework --jq .id` and the same call for `objectstack` both return 1136691870, and `framework` reports full_name objectstack-ai/objectstack -- a rename redirect, so nothing was broken, every URL just cost a 301. Fixed the one constant `gitConfig.repo` in apps/docs/lib/layout.shared.tsx ('framework' -> 'objectstack') and added a comment recording why it must track the current name. The sweep question the card asked is answered with a measurement rather than a judgement call: there is NO independent repository-name literal anywhere under apps/docs/ -- all three link types are pure concatenations of this single constant, so the correct sweep is exactly one line wide. Docs-site only, no changeset; skip-changeset applied additively and read back alongside the size-labeler's own labels.",
      "tests": "GREP PATTERN (filesystem-level, untracked included): grep -rnaiE 'github\\.com|objectstack-ai|framework' apps/docs/ --exclude-dir=node_modules --exclude-dir=.next --exclude-dir=.turbo . A bare 'framework' grep was deliberately avoided -- the word is legitimate prose repo-wide. FULL HIT LIST (10): lib/layout.shared.tsx:5 repo:'framework' = THE BUG (fixed); lib/layout.shared.tsx:4 user:'objectstack-ai' = correct; lib/layout.shared.tsx:20, app/[lang]/page.tsx:195, app/[lang]/docs/[[...slug]]/page.tsx:31 = the three template literals that READ the constant; vercel.json:3 \"framework\":\"nextjs\" = Vercel build-preset key, unrelated, NOT touched; app/[lang]/page.tsx:25,51 + blog/[[...slug]]/page.tsx:201 'metadata framework for AI-written apps' + page.tsx:406 '7 framework adapters' = prose. Second pattern: git ls-files -z | xargs -0 grep -na 'gitConfig' repo-wide returned 6 lines, all in those same 3 files. || VERIFICATION was against a local pnpm --filter @objectstack/docs build + next start -p 3457, NOT the live site (production has not redeployed since ~16:55 per #12333). Rendered hrefs extracted from served HTML, then curl -sI: NAV LINK (baseOptions().githubUrl, seen on /docs) before https://github.com/objectstack-ai/framework -> HTTP/2 301, after https://github.com/objectstack-ai/objectstack -> HTTP/2 200 with no location header. HERO BUTTON (app/[lang]/page.tsx:195, seen on /) emits the same URL string as the nav link so it shares that measurement; confirmed separately in the homepage HTML. EDIT LINK (per-page) before https://github.com/objectstack-ai/framework/blob/main/content/docs/ui/views.mdx -> HTTP/2 301, after .../objectstack/blob/main/content/docs/ui/views.mdx -> HTTP/2 200; also checked .../content/docs/index.mdx -> HTTP/2 200. WHOLE-SITE: find .next/server/app -type f -print0 | xargs -0 grep -ohaE 'github\\.com/objectstack-ai/framework' | wc -l = 3656 before, 0 after, across 411 .html + 2048 .rsc + 811 .body artifacts (1222 pages). Remaining rendered repo names are all legitimate (objectstack 1632, objectui, hotcrm, claude-plugin, mycompany/crm example, google/cel-spec, cel-js, mingo, changesets); an apparent objectstack-ai/objec hit is an RSC chunk boundary splitting a prose URL, not a truncated link. || GATES derived with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (script read the merge base itself, 1 path), then RE-RUN AFTER THE FINAL COMMIT at HEAD 06412954e with a clean tree: check:page-declaration-shape 'check-page-declaration-shape: OK -- 34 page entries across 2189 sources'; check:published-files 'check:published-files -- 69 publishable package(s)'; check:test-source-alias 'check-test-source-alias OK -- 72 packages with tests scanned'; check:type-source-resolution 'check-type-source-resolution OK -- 93 tsc program(s) across 77 packages'; check:nul-bytes 'check-nul-bytes: OK (scanned 6836 text file(s) ... no raw ASCII control bytes)'; pnpm --filter @objectstack/docs typecheck exit 0. NOT-VACUOUS PROOF: tsc --noEmit --listFiles lists apps/docs/lib/layout.shared.tsx (1 hit), so typecheck genuinely covered the edited file. FULL-REPO pnpm lint (eslint . --no-inline-config) ran clean: VERDICT command-exit 0, 40s -- no narrowing was needed. An earlier lint attempt aborted with a V8 heap abort (exit 134) at --max-old-space-size=4096 while the next start server still held memory; that was a RESOURCE failure, not a lint finding, and is recorded as such, not as a red gate. || DECLARED NARROWING: this host is macOS with no flock, so scripts/pm/os-verify-lock.sh ran every heavy command in its DECLARED UNLOCKED MODE -- the shared verify lock was never taken and nothing was serialized. Every run carries 'VERDICT ... UNLOCKED (declared)'. Disclosed in the PR body as the script instructs. || CI AT REPORT TIME (REST, since the GraphQL pool is exhausted -- gh pr checks returns 'API rate limit already exceeded'): 26 check runs on 06412954e -- 11 success, 9 skipped, 6 in_progress, 0 failures. Passing guards include 'No other open PR may claim the same issue', 'No other open PR may claim the same single-writer path', and 'Part-of PR must not also close its card'. Still in_progress: Build Docs, Check Changeset, Lint & Repo Gates, Type Check (consumer gates / debt ledger / source gates). Reported at draft-PR time per contract rather than waiting for convergence.",
      "open_questions": [],
      "out_of_scope_findings": [
        "NOT FILED -- the dispatch reserved filing for the PM ('If you find them, say so in the report and I will file it'), so no issues were created. Finding 1: content/docs.site.json carries a SECOND, independent repository-name constant -- page.repoBaseUrl (line 63) and themeConfig.socials[].url (line 40) are both https://github.com/objectstack-ai/spec. objectstack-ai/spec is ALSO a stale name: curl -sI returns HTTP/2 301 with location: https://github.com/objectstack-ai/objectstack. It has ZERO runtime consumers -- the only references to repoBaseUrl anywhere in the repo are gate scripts mentioning the filename as a path-hint fixture -- so it does not reach rendered output today, but it is inert config spelling a third name, which is exactly the shape someone wires up later.",
        "NOT FILED (same reason). Finding 2: stale objectstack-ai/spec links in published prose -- content/blog/metadata-driven-architecture.mdx:586 and content/blog/protocol-first-development.mdx:335,851 DO render (they are the 4 rendered 'spec' hits the whole-site sweep found), plus CONTRIBUTING.md:38,57,440, docs/notes/airtable-dashboard-analysis.mdx:11, and the link-reference block at the bottom of the root CHANGELOG.md. Note docs/audits/2026-06-handwritten-docs-accuracy-followups.md:40 already flagged these for human follow-up and declined to rewrite them, so a card here should reference that prior rather than re-litigate it.",
        "Scope was held to apps/docs/ as instructed -- root README.md, docker/README.md and packages/** were not swept and are not covered by any claim in this report."
      ]
    }
  7. os-zhuang commented on Aug 25, 2026

    @os-zhuang
    ContributorAuthor

    ACCEPT — PR #12364, 1 file, +7/-1: the constant plus a comment recording why it must track the current name.

    The card asked for a judgement about sweep width and got a measurement instead, which is the better answer: there is no independent repository-name literal anywhere under apps/docs/. All three link types are pure concatenations of this one constant, so the correct sweep is exactly one line wide — established with a URL-shaped grep (a bare framework grep was deliberately avoided, since the word is legitimate prose repo-wide) plus a gitConfig sweep, with the full 10-hit list in the report and each hit classified, including vercel.json's "framework": "nextjs" build-preset key correctly identified as unrelated.

    Whole-site proof rather than a spot check: github.com/objectstack-ai/framework appears 3656 times across the built artifacts before (411 .html + 2048 .rsc + 811 .body, 1222 pages) and 0 after. Redirect hops measured directly: nav link and edit link both HTTP/2 301 before, HTTP/2 200 with no location after.

    Verified against a local production build, correctly refusing to cite the live site while #12333 holds.

    The two findings I said I would file — both confirmed independently before filing

    I re-measured rather than relaying, and both hold, with one detail worth adding: objectstack-ai/spec is a third stale name, not a different repository. gh api repos/objectstack-ai/spec returns full_name: objectstack-ai/objectstack, id 1136691870 — the same id as framework and as objectstack. So the repo has been renamed at least twice and links to both former names survive.

    Confirmed in the tree: content/docs.site.json spells it twice (themeConfig.socials[].url line 40, page.repoBaseUrl line 63), and it renders in published prose — protocol-first-development.mdx (2 hits) and metadata-driven-architecture.mdx (1 hit).

    Filed as a standalone card, not a sub-issue of #12243: the epic's definition of done passes without it, and I am not repeating the lane error I made on this very card.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions