Fix internal links to old /docs/concepts/ URLs missed by #21072 - #21138
Conversation
PR #21072 rewrote 79 files of content/ links from old /docs/concepts/* to their current /docs/iac/concepts/*, /docs/esc/concepts/*, and /docs/reference/glossary/* destinations, but its sweep covered content/ markdown links only. Three files outside that scope still pointed at old dead-hop paths: - layouts/migrate/terraform.html: a template href, not a content link - assets/openapi/tag-intros/stacks.md: OpenAPI docs intro fragment - content/docs/iac/concepts/resources/_index.md: a client-side JS hash-redirect map (5 of its 22 entries still pointed at the old paths, doing the same job the map exists for but landing on another redirect hop instead of the final page) Each old path was verified against its live redirect chain before rewriting, confirming the new destination resolves 200 directly: - /docs/concepts/vs/terraform -> /docs/iac/comparisons/terraform/ - /docs/concepts/stack/ -> /docs/iac/concepts/stacks/ - /docs/concepts/resources/components -> /docs/iac/concepts/components/ - /docs/concepts/resources/names -> /docs/iac/concepts/resources/names/ - /docs/concepts/resources/get -> /docs/iac/concepts/functions/get-functions/ The #urns and #autonaming anchors were confirmed present on the new resources/names/ page. content/blog/why-choose-pulumi-over-terraform/index.md is intentionally left untouched here; it is still blocked by open PRs #21062 and #21066 and is tracked separately. node ./scripts/lint/lint-markdown.js and ./scripts/prettier.sh --check both pass on the changed files (the one markdown-lint finding on assets/openapi/tag-intros/stacks.md is a pre-existing missing-heading warning on master, unrelated to this change). --- 🧠 *This PR was created by [workprentice](https://github.com/workprentice).*
|
Your site preview for commit c2c0c3a is ready! 🎉 http://www-testing-pulumi-docs-origin-pr-21138-c2c0c3a0.s3-website.us-west-2.amazonaws.com Changed pages: |
Lighthouse Performance ReportCommit: c2c0c3a | Metric definitions
|
Pre-merge Review — Last updated 2026-08-26T20:41:12ZTip Summary: A follow-up link cleanup to #21072, now five commits across fifteen files: the two client-side redirect maps in Review confidence:
Investigation log
🔍 Verification trail37 claims extracted · 35 verified · 0 unverifiable · 0 contradicted · 1 framing-drift · 2 detector findingsFrom
From
New in
New in this refresh (mention by @workprentice[bot]):
📊 Editorial balanceSingle-subject post; balance check N/A. 🚨 Outstanding in this PRNo outstanding findings.
|
…g stale content links PR #21138 fixed 3 non-content/ surfaces (an asset, the resources hash-redirect map, and a layout template) but left several sibling defects of the same class: - theme/src/ts/redirects.ts: a client-side hash-redirect map for the old /docs/intro/concepts/programming-model/ page pointed all 34 entries at dead /docs/concepts/* hops. Rewrote every entry to its live /docs/iac/concepts/* (or /docs/iac/concepts/inputs-outputs/*, /docs/iac/concepts/providers/*, etc.) destination, verified 200 with no further hop. - theme/src/ts/toc.ts: the left-nav active-state map still keyed off the old /docs/concepts/ path. - content/docs/iac/concepts/resources/_index.md: the hash-redirect map added by #21138 itself was missing trailing slashes on 16 of its 28 targets, each of which 302-redirects to the slashed form -- the same dead-hop defect this whole cleanup exists to remove. Added trailing slashes throughout. - Six remaining content files (archetypes template, two blog posts, the insights search reference-link footnotes, and the k8s operator integration page) still linked to old /docs/concepts/* paths; rewrote to their current /docs/iac/concepts/* destinations. Every new destination verified live against https://www.pulumi.com with redirects disabled: all return 200 directly. A further stale link was found in static-prebuilt/ ESC SDK reference HTML, but those files are generated from pulumi/esc's own SDK docstrings at build time, so fixing them here would be overwritten on next regeneration -- tracked separately for a pulumi/esc-side fix.
|
CI is green on the latest commit (f256b55): build, example-code tests, and social-review all passed. This commit extends the original fix (3 files) to also cover sibling defects of the same class found in an independent repo-wide audit: the The pre-merge review is showing |
|
🤖 Review updated on @workprentice[bot]'s request. |
Fixes the outstanding finding from the pre-merge review: - content/docs/iac/guides/clouds/aws/eks.md:307 -- a two-line markdown link the earlier single-line grep missed; repoints to the canonical /docs/iac/concepts/resources/options/transforms/. - scripts/search/rank.js:80 -- the search-ranking boost for concepts pages checked the retired /docs/concepts/ prefix, so it silently fell through to the generic docs score (860) instead of 890. - theme/src/ts/redirects.ts -- "#outputs-and-strings" now lands on the section anchor (#using-string-interpolation) instead of the top of the page, matching the other 33 entries' precision and the stub page's own redirect_to target. content/blog/why-choose-pulumi-over-terraform/index.md's three absolute-URL survivors are intentionally left out of this PR: that file already has two open PRs against it (#21062, #21066) and is tracked separately.
|
@claude #update-review Fixed all three surviving
Intentionally not touched in this PR: Left |
|
@workprentice for this and all future PRs in this repo, please work the ALL the findings to completion. I need ALL of them either resolved or refuted (preferably with evidence I can verify) before I review the PR. |
Review flagged this as a sibling of the /docs/concepts/ prefix defect this PR fixes: content/docs/using-pulumi no longer exists, and every remaining /docs/using-pulumi/... occurrence under content/docs/ is an `aliases:` entry (a historical redirect source), not a page's own `url:`. No indexed page's href ever starts with /docs/using-pulumi/, so the branch never fired -- pages that used to live there now score 860 or 870 via fallthrough, same as any other docs page. The content that used to live under /docs/using-pulumi/ moved to three different trees (iac/, insights/policy/, administration/) with no single successor prefix, so there's no one replacement string to substitute -- removing the dead branch is the honest fix rather than repointing it.
|
@claude #update-review CI is green on the new commit (c2c0c3a). All three low-confidence items from the last review pass are now closed out:
Please refresh the pre-merge review against c2c0c3a. |
|
@CamSoper Understood, and applied here: every finding from the last review pass -- Outstanding and Low-confidence alike -- is now resolved or refuted with checkable evidence rather than left open:
I've asked for a review refresh against the current HEAD (c2c0c3a) so you're looking at a clean 0/0 state, not my claim of one. I'll hold this pattern -- work every finding to ground truth, not just the blocking ones, before asking for review -- on future PRs in this repo as well. 🧠 *This comment was posted by workprentice on behalf of the Pulumi SEO/AEO agent, acting autonomously (no human principal accountable for this scheduled run). |
|
🤖 Review updated on @workprentice[bot]'s request. |
…output Addresses both Outstanding findings and both Low-confidence findings from the review bot on this PR. Outstanding 1 -- SCAN_ROOTS omitted archetypes/ and static/, so a stale /docs/concepts/* link born in a page's own generation scaffold (archetypes/templates/template/index.md, which every new template page is generated from) went unseen forever, only to be caught in content/ after it had already been scaffolded into a real page. Added archetypes, static, and scripts to SCAN_ROOTS. Including scripts pulled in one occurrence, scripts/search/rank.js:80 (a historical-href check, not a live link) -- baselined it rather than dropping the scripts root, since a baselined known occurrence still ratchets while an unscanned directory does not. static/ added zero new occurrences (verified: it's mostly binary images, nothing text-scannable matched). Regenerated the baseline against master state (not this branch's own commits) so it describes what master actually has today; PR #21138 already removed the prior rank.js occurrence via a different code path, so this branch's own widened scan needed the fresh baseline to stay green. Outstanding 2 -- --print-baseline printed a flat {path: count} object, but loadBaseline() reads parsed.files || {}. Regenerating the baseline the obvious way (redirecting --print-baseline output to the baseline file) silently produced a baseline that loads as empty, then every baselined file fails with no hint why. Fixed --print-baseline to emit the same {_note, files} envelope the reader expects, building the files object from the sorted violation-map keys directly rather than using a JSON.stringify replacer keyed off Object.keys() (that reads as a filter and silently drops any key not already present). Also added --print-baseline to the Usage: block, which previously only documented it inside main()'s own comments. Low-confidence 1 -- implemented: a green run now prints one summary line instead of ~11 file headers and ~56 occurrence lines. Full detail only prints when the check actually fails. Verified: a fabricated violation still prints full file-by-file detail and exits 1; a clean run prints one line and exits 0. Low-confidence 2 -- decision (not code): kept the ratchet as a count-only check rather than switching to line-level tracking, since the baseline is meant to be short-lived and line tracking isn't worth the added churn for a file that should be deleted once #21138 and #21145 merge. Documented the limitation directly in the baseline's own _note so the next reader isn't surprised: fixing one stale link and introducing a different one in the same file keeps the count unchanged and still passes. Verified end-to-end: self-test passes (9/9 fixtures), make-equivalent full scan is green with the new summary line, --print-baseline output round-trips through loadBaseline() as 13 non-empty entries, and a fabricated /docs/concepts/testing/ link injected into archetypes/templates/template/index.md (a root only reachable after this fix) correctly fails the check with exit 1 and full detail, then cleanly reverts to green.
|
Addressed both halves of this finding. (a) Description precision. Fixed the wording in item 5: it now says no page anywhere in (b) The real defect, out of scope here. Fixed in #21155, following the same pattern already accepted for the blog file split with #21145: a stray/colliding @claude #update-review |
|
🤖 Review updated on @workprentice[bot]'s request. |
…output Addresses both Outstanding findings and both Low-confidence findings from the review bot on this PR. Outstanding 1 -- SCAN_ROOTS omitted archetypes/ and static/, so a stale /docs/concepts/* link born in a page's own generation scaffold (archetypes/templates/template/index.md, which every new template page is generated from) went unseen forever, only to be caught in content/ after it had already been scaffolded into a real page. Added archetypes, static, and scripts to SCAN_ROOTS. Including scripts pulled in one occurrence, scripts/search/rank.js:80 (a historical-href check, not a live link) -- baselined it rather than dropping the scripts root, since a baselined known occurrence still ratchets while an unscanned directory does not. static/ added zero new occurrences (verified: it's mostly binary images, nothing text-scannable matched). Regenerated the baseline against master state (not this branch's own commits) so it describes what master actually has today; PR #21138 already removed the prior rank.js occurrence via a different code path, so this branch's own widened scan needed the fresh baseline to stay green. Outstanding 2 -- --print-baseline printed a flat {path: count} object, but loadBaseline() reads parsed.files || {}. Regenerating the baseline the obvious way (redirecting --print-baseline output to the baseline file) silently produced a baseline that loads as empty, then every baselined file fails with no hint why. Fixed --print-baseline to emit the same {_note, files} envelope the reader expects, building the files object from the sorted violation-map keys directly rather than using a JSON.stringify replacer keyed off Object.keys() (that reads as a filter and silently drops any key not already present). Also added --print-baseline to the Usage: block, which previously only documented it inside main()'s own comments. Low-confidence 1 -- implemented: a green run now prints one summary line instead of ~11 file headers and ~56 occurrence lines. Full detail only prints when the check actually fails. Verified: a fabricated violation still prints full file-by-file detail and exits 1; a clean run prints one line and exits 0. Low-confidence 2 -- decision (not code): kept the ratchet as a count-only check rather than switching to line-level tracking, since the baseline is meant to be short-lived and line tracking isn't worth the added churn for a file that should be deleted once #21138 and #21145 merge. Documented the limitation directly in the baseline's own _note so the next reader isn't surprised: fixing one stale link and introducing a different one in the same file keeps the count unchanged and still passes. Verified end-to-end: self-test passes (9/9 fixtures), make-equivalent full scan is green with the new summary line, --print-baseline output round-trips through loadBaseline() as 13 non-empty entries, and a fabricated /docs/concepts/testing/ link injected into archetypes/templates/template/index.md (a root only reachable after this fix) correctly fails the check with exit 1 and full detail, then cleanly reverts to green.
PR #21138 and PR #21145 (the cleanup pass this guard exists to protect) both merged today. Every one of the 12 baselined files now has 0 real occurrences of an internal /docs/concepts/* link on master, so the 57-occurrence allowance list was pure dead weight: a future PR could have introduced up to that many brand-new stale links per file and the guard would stay green and silent, which is exactly the regression it exists to catch. Rebased onto current master and reset the baseline to {}, updating its _note and this script's own doc comments to stop describing the two PRs as still open. Verified against the merged tree: a full scan finds 0 occurrences in all 12 previously-baselined files, and a fresh --print-baseline confirms an empty {_note, files: {}} envelope is the correct state.
What
Post-merge verification follow-up on the redirect-hop cleanup shipped in #21072. #21072 rewrote 79 files of
content/links from old/docs/concepts/*paths to their current destinations (/docs/iac/concepts/*,/docs/esc/concepts/*,/docs/reference/glossary/*), but its sweep matched links inside markdown body text undercontent/. This PR closes out the rest of that defect class across five commits:layouts/migrate/terraform.html(a Hugo templatehref),assets/openapi/tag-intros/stacks.md(an OpenAPI docs intro fragment), andcontent/docs/iac/concepts/resources/_index.md(a client-side JS hash-redirect map with several stale entries).theme/src/ts/redirects.tsmap (every entry pointed at a dead hop),theme/src/ts/toc.ts, missing trailing slashes on 16 of 28 entries in theresources/_index.mdmap added by commit 1 (each 302-redirecting to the slashed form -- the same defect this cleanup targets), and six more content files with leftover links.content/docs/iac/guides/clouds/aws/eks.md:307,scripts/search/rank.js:80(the concepts-prefix check), andtheme/src/ts/redirects.ts's#outputs-and-stringsanchor precision.<meta http-equiv="refresh">fallback on the two retired programming-model stub pages, which still pointed at/docs/concepts(a 302-then-301 chain) instead of the final/docs/iac/concepts/destination.scripts/search/rank.js's/docs/using-pulumi/ranking branch.content/docs/using-pulumino longer exists as a tree, and no page anywhere incontent/docs/sets aurl:under that prefix -- verified independently by grepping everyurl:frontmatter field repo-wide -- so no indexed page ever carried that href and the branch never fired. (Two occurrences under that prefix are live body links rather thanaliases:entries --content/docs/iac/guides/migration/import/_index.md:501andcontent/docs/iac/comparisons/terraform/opentofu.md:148-- but neither is a page's ownurl:, and both are broken/hopping links in their own right, fixed separately in Fix /docs/using-pulumi/ link defects and remaining /docs/iac/concepts/options/* redirect hops #21155.) The content that used to live there is now spread acrossiac/,insights/policy/, andadministration/with no single successor prefix, so removing the branch (rather than repointing it) is the honest fix.Deliberately out of scope
content/blog/why-choose-pulumi-over-terraform/index.md's three/docs/concepts/stacks/occurrences (lines 33, 49, 147) are fixed in a separate PR, #21145, rather than folded in here: two other open PRs (#21062, #21066) also touch this file, and keeping the fix isolated avoids stacking unrelated diffs on top of an already-contested file.git merge-treechecks (documented in #21145's description) confirm no conflict with either PR's hunks.A further stale link was found in
static-prebuilt/docs/reference/pkg/{python,dotnet,nodejs}/.../esc-sdk*(generated ESC SDK reference HTML). Those files are generated at build time frompulumi/esc's own SDK docstrings, so a direct edit here would be silently overwritten on next regeneration -- tracked on a separate board card for a pulumi/esc-side fix instead.Verification
Each old path's live redirect chain was resolved before rewriting, confirming the new destination is the actual final
200(checked with redirects disabled against pulumi.com):/docs/concepts/vs/terraform/docs/iac/comparisons/terraform//docs/concepts/stack//docs/iac/concepts/stacks//docs/concepts/resources/components/docs/iac/concepts/components//docs/concepts/resources/names(+#autonaming,#urns)/docs/iac/concepts/resources/names/(anchors confirmed present)/docs/concepts/resources/get/docs/iac/concepts/functions/get-functions//docs/concepts(meta refresh target)/docs/iac/concepts/redirects.tstargets and all 28resources/_index.mdmap targetsA repo-wide sweep at the current HEAD confirms the only surviving
/docs/concepts/...links anywhere in the tree are the three deferred blog URLs covered by #21145, plusaliases:entries (which are supposed to reference the old path), review-pipeline testdata, and externalkubernetes.io/hashicorp.comlinks.Checks
node ./scripts/lint/lint-markdown.jsand./scripts/prettier.sh --checkboth pass on all changed files across all five commits.🧠 This PR was created by workprentice on behalf of the Pulumi SEO/AEO agent, acting autonomously (no human principal accountable for this scheduled run).