Context
Operator-directed production investigation (2026-07-02): Google Cloud statistics report a sustained 404 wave on neomjs.com. One of the two root causes lives in this repo's data-sync pipeline: the hourly job advances the advertised route surface (sitemap.xml, llms.txt, portal data indexes) but never syncs the learn/** markdown those routes point at. Operator ruling on the fix side (verbatim): "you already figured out the solutions, so of course i approve" — workflow-side sync approved; 404s are causing Googlebot ranking downgrades, so this is business-tier, not cosmetic.
Live latest-open sweep: checked latest 20 open issues at 2026-07-02T16:15Z; no equivalent found. A2A in-flight sweep: latest 30 all-status messages at 16:15Z; no competing claim (my own 16:06Z investigation broadcast announced this filing).
The Problem
The Push Data to neomjs/pages step copies, hourly: devindex users.jsonl, apps/portal/resources/data/*.json (flat glob), sitemap.xml, llms.txt, and the six resources/content/* archive buckets. It does not copy learn/**.
neomjs/pages (= neomjs.github.io) is where human traffic is served. Its node_modules/neo.mjs/learn/** tree only refreshes on release-time/manual full deploys. Verified consequences (2026-07-02):
pages:node_modules/neo.mjs/learn/blog/ holds 11 files, newest cohort v10-era; dev has 14 — every post since the last full deploy is an advertised dead link (specimen: the April time-capsule post, merged 11:52Z today via #14465, present in the hourly-synced sitemap, absent in pages).
learn/tree.json (the SPA's learn navigation index) also lives in the unsynced tree — so even the nav index on production is release-frozen while sitemap.xml advances hourly. Index-advances-without-content is structural, exactly as the operator reported.
- The flat
*.json glob misses apps/portal/resources/data/ subdirectories (e.g. tickets/v*/, pulls/latest/ chunk trees), which drift the same way between full deploys.
Route-class blast note: this is one of two stacked causes. The sibling cause (deployment middleware frozen by dirty-checkout halts) is #14478 + private-repo work; this ticket heals the human-traffic class independently of that chain.
The Architectural Reality
- Workflow:
.github/workflows/data-sync-pipeline.yml, Push Data to neomjs/pages step — the established sync pattern is rm -rf + cp -r per directory ("syncing deletions natively via git", per the Epic #11187 7-bucket fan-out comment in the workflow itself).
- Pages layout: content roots under
temp_pages/node_modules/neo.mjs/ (verified live via the GitHub contents API — the blog listing above).
- Neo-side commit step (dev push) is untouched:
learn/** is authored source in this repo; only the pages-push step needs the additional copy set.
- The pages commit already uses
--no-verify (no archaeology guard on the pages clone) — no new commit-gating concerns.
The Fix
In the Push Data to neomjs/pages step:
- Add
learn to the deletion-synced copy set, same pattern as the content buckets: rm -rf temp_pages/node_modules/neo.mjs/learn
cp -r learn temp_pages/node_modules/neo.mjs/
- Replace the flat portal-data copy with a deletion-synced recursive copy of
apps/portal/resources/data/ (covers the chunked subdirectories).
- Extend the pages-side change-detection
git status -s path list and git add set accordingly (git add -A on the two synced roots).
No new scripts, no new secrets, no .mjs files (structural pre-flight N/A).
Acceptance Criteria
Out of Scope
- The middleware freeze + auto-deploy leg (private-repo work, routed to the operator; neo-side sibling is #14478).
- Release-time full-tree pages deploys (unchanged; this ticket only closes the hourly gap between them).
apps/portal/index.html / app-shell assets (release-owned, not content-churned).
Avoided Traps
- Middleware-side-only fix rejected: human traffic proxies to pages; a middleware fix alone leaves the human class dead.
- Syncing the whole repo tree rejected: the copy set stays scoped to content that routes advertise (learn + portal data), keeping the hourly commit small and reviewable.
- Symlink/submodule schemes rejected: the workflow's established
rm -rf+cp -r deletion-sync pattern is proven and native to the pages history.
Decision Record impact
none — aligned with the Epic #11187 fan-out pattern already governing this workflow step.
Related
#14478 (sibling root cause — tracked runtime files freeze the middleware pulls) · #14465 (live dead-link specimen) · #14311/PR #14470 (route reshape whose propagation depends on deletion sync) · Epic #11187 (the workflow's content fan-out pattern) · the #14470 cycle-3 deployment-blast-radius lesson (public routes are deployment substrate).
Origin Session ID: 4ebdc396-4bd7-4dee-b16b-23baf188a622
Retrieval Hint: query_raw_memories("neomjs.com 404 wave pages learn sync middleware freeze deployment blast radius")
Context
Operator-directed production investigation (2026-07-02): Google Cloud statistics report a sustained 404 wave on neomjs.com. One of the two root causes lives in this repo's data-sync pipeline: the hourly job advances the advertised route surface (sitemap.xml, llms.txt, portal data indexes) but never syncs the
learn/**markdown those routes point at. Operator ruling on the fix side (verbatim): "you already figured out the solutions, so of course i approve" — workflow-side sync approved; 404s are causing Googlebot ranking downgrades, so this is business-tier, not cosmetic.Live latest-open sweep: checked latest 20 open issues at 2026-07-02T16:15Z; no equivalent found. A2A in-flight sweep: latest 30 all-status messages at 16:15Z; no competing claim (my own 16:06Z investigation broadcast announced this filing).
The Problem
The
Push Data to neomjs/pagesstep copies, hourly:devindexusers.jsonl,apps/portal/resources/data/*.json(flat glob),sitemap.xml,llms.txt, and the sixresources/content/*archive buckets. It does not copylearn/**.neomjs/pages(=neomjs.github.io) is where human traffic is served. Itsnode_modules/neo.mjs/learn/**tree only refreshes on release-time/manual full deploys. Verified consequences (2026-07-02):pages:node_modules/neo.mjs/learn/blog/holds 11 files, newest cohort v10-era;devhas 14 — every post since the last full deploy is an advertised dead link (specimen: the April time-capsule post, merged 11:52Z today via#14465, present in the hourly-synced sitemap, absent in pages).learn/tree.json(the SPA's learn navigation index) also lives in the unsynced tree — so even the nav index on production is release-frozen whilesitemap.xmladvances hourly. Index-advances-without-content is structural, exactly as the operator reported.*.jsonglob missesapps/portal/resources/data/subdirectories (e.g.tickets/v*/,pulls/latest/chunk trees), which drift the same way between full deploys.Route-class blast note: this is one of two stacked causes. The sibling cause (deployment middleware frozen by dirty-checkout halts) is #14478 + private-repo work; this ticket heals the human-traffic class independently of that chain.
The Architectural Reality
.github/workflows/data-sync-pipeline.yml,Push Data to neomjs/pagesstep — the established sync pattern isrm -rf+cp -rper directory ("syncing deletions natively via git", per the Epic#111877-bucket fan-out comment in the workflow itself).temp_pages/node_modules/neo.mjs/(verified live via the GitHub contents API — the blog listing above).learn/**is authored source in this repo; only the pages-push step needs the additional copy set.--no-verify(no archaeology guard on the pages clone) — no new commit-gating concerns.The Fix
In the
Push Data to neomjs/pagesstep:learnto the deletion-synced copy set, same pattern as the content buckets:rm -rf temp_pages/node_modules/neo.mjs/learn cp -r learn temp_pages/node_modules/neo.mjs/apps/portal/resources/data/(covers the chunked subdirectories).git status -spath list andgit addset accordingly (git add -Aon the two synced roots).No new scripts, no new secrets, no
.mjsfiles (structural pre-flight N/A).Acceptance Criteria
learn/**(includinglearn/tree.json) syncs totemp_pages/node_modules/neo.mjs/learn/hourly with deletion sync (removed/renamed source files disappear from pages — required for route renames like the#14311Introduction reshape to propagate instead of leaving stale duplicates).apps/portal/resources/data/**syncs recursively (subdirectory chunk trees included), deletion-synced.git addcover the new paths (no silent "No changes detected" when onlylearn/**changed).learn/**change ondev, the changed file is present inneomjs/pages— specimen check:learn/blog/the-organism-already-existed.mdexists in pages.Out of Scope
apps/portal/index.html/ app-shell assets (release-owned, not content-churned).Avoided Traps
rm -rf+cp -rdeletion-sync pattern is proven and native to the pages history.Decision Record impact
none — aligned with the Epic
#11187fan-out pattern already governing this workflow step.Related
#14478 (sibling root cause — tracked runtime files freeze the middleware pulls) ·
#14465(live dead-link specimen) ·#14311/PR#14470(route reshape whose propagation depends on deletion sync) · Epic#11187(the workflow's content fan-out pattern) · the#14470cycle-3deployment-blast-radiuslesson (public routes are deployment substrate).Origin Session ID: 4ebdc396-4bd7-4dee-b16b-23baf188a622
Retrieval Hint:
query_raw_memories("neomjs.com 404 wave pages learn sync middleware freeze deployment blast radius")