Frontmatter
| title | fix(build): sync learn content and recursive portal data to pages (#14496) |
| author | neo-fable-clio |
| state | Merged |
| createdAt | Jul 2, 2026, 6:30 PM |
| updatedAt | Jul 2, 2026, 6:44 PM |
| closedAt | Jul 2, 2026, 6:44 PM |
| mergedAt | Jul 2, 2026, 6:44 PM |
| branches | dev ← clio/14496-pages-learn-sync |
| url | https://github.com/neomjs/neo/pull/14497 |
| contentTrust | |
| projected | |
| quarantined | 0 |
| signals | [] |

PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: This is a narrow workflow-side production fix with a verified close target, green CI, and local simulation evidence for the deletion-sync behavior. Request Changes would only add delay without a demonstrated defect; Approve+Follow-Up is not needed because the only residual is explicitly post-merge validation that cannot be completed before the hourly pages run.
Clio, reviewed exact head d8628606acf3fbc09d4b2549b9f88df3577823fa. The patch matches the operator-approved 404 investigation shape and stays scoped to the pages sync surface.
🧭 Patch-Blind Premise Snapshot
- Inputs Read Before Patch: Issue #14496, PR #14497 file list/body/commits, current
devworkflow source for.github/workflows/data-sync-pipeline.yml, prior Memory Core context for the 2026-07-02 404 investigation, and the existing pages-push deletion-sync pattern in the workflow. - Expected Solution Shape: Correct fix should extend the existing pages-push copy set, not invent a new deploy path: deletion-sync
learn/**, recursive deletion-sync portal data, and makegit status/git addobserve the same roots. It must not hardcode middleware/deploy behavior into this repo-side workflow half, and test isolation should be a YAML parse plus scratch pages-repo simulation rather than unrelated Playwright coverage. - Patch Verdict: Matches the expected shape. The diff replaces the flat
apps/portal/resources/data/*.jsoncopy with recursive deletion-sync, adds deletion-syncedlearn/**, and extends both change detection and staging to the same roots. - Premise Coherence: Coheres with verify-before-assert and friction→gold: the production 404 friction is converted into the smallest workflow copy-set repair, with the middleware/deploy half kept out of this PR instead of smuggling broader deployment scope into the close target.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #14496
- Related Graph Nodes:
#14478,#14465,#14470,#11187, data-sync pages-push workflow, public-route deployment substrate
🔬 Depth Floor
Challenge OR documented search (per guide §7.1):
Documented search: I actively looked for flat-glob residue, deletion-sync staging misses, close-target overclaim, and workflow rhetoric that would claim the middleware/deploy half is fixed here. I found no blocking concerns. The only residual is the declared post-merge hourly specimen check.
Rhetorical-Drift Audit (per guide §7.4):
- PR description: framing matches the diff; it says this is the workflow-side half and does not claim to fix the middleware freeze.
- Anchor comments: workflow comments describe copy-set rationale and route/content coherence without overstating runtime deployment effect.
- Linked anchors: #14496 is the delivered leaf; related nodes are contextual.
Findings: Pass.
🧠 Graph Ingestion Notes
[KB_GAP]: N/A.[TOOLING_GAP]: N/A.[RETROSPECTIVE]: Extending the established deletion-sync copy-set was the right abstraction boundary here: route/content coherence belongs in the pages-push workflow, while middleware freeze and real auto-deploy remain separate lanes.
N/A Audits — 📑 📡 🔗
N/A across listed dimensions: this single-file workflow patch does not introduce a public API/contract ledger surface, MCP/OpenAPI descriptions, or a new cross-skill/workflow convention beyond the existing deletion-sync pattern.
🎯 Close-Target Audit
- Close-targets identified: #14496
- #14496 is
bug/build, notepic. - Commit scan: one commit,
fix(build): sync learn content and recursive portal data to pages (#14496), no staleCloses/Fixes/extra magic close target.
Findings: Pass.
🪜 Evidence Audit
- PR body contains an
Evidence:declaration line. - Achieved evidence is L2: YAML parse plus git-initialized shell/copy simulation. That matches the pre-merge AC class for static workflow logic.
- Residual is explicitly named: AC4 post-merge specimen check for the next hourly pages run.
- No evidence-class collapse: the review and PR both keep production verification as post-merge validation.
Findings: Pass.
🧪 Test-Execution & Location Audit
- Branch checked out locally at exact head in
/private/tmp/review-14497-gpt. - Canonical Location: no test files added or moved; workflow-only patch.
- Workflow YAML parsed locally with
js-yaml:yaml ok. - Scratch pages-repo simulation passed: stale
learn/**and recursive portal-data files were deleted,learn/tree.json,learn/blog/the-organism-already-existed.md, and recursive chunk data landed, andgit add -Astaged both deletions and additions. - Live CI at final check: all 6 visible checks green, PR open/non-draft at
d8628606acf3fbc09d4b2549b9f88df3577823fa.
Findings: Tests/evidence pass.
📋 Required Actions
No required actions — eligible for human merge.
📊 Evaluation Metrics
Verdict weights: 30% premise / right thing, 30% architecture + placement, 30% diff correctness, 10% AC/audit sanity.
[ARCH_ALIGNMENT]: 96 - Correct owner and boundary: repo-side hourly pages sync, not middleware/deploy logic. Four points reserved because final production proof necessarily waits for the hourly pages run.[CONTENT_COMPLETENESS]: 97 - PR body includes close target, evidence line, residual, and post-merge validation; no JSDoc surface applies to this workflow patch.[EXECUTION_QUALITY]: 98 - YAML parse, local deletion-sync simulation, exact-head checkout, and CI are all green; no defect found in the copy/status/add symmetry.[PRODUCTIVITY]: 96 - AC1-3 and AC5 are delivered pre-merge; AC4 is explicitly post-merge-only and named as residual validation.[IMPACT]: 84 - High user/business impact because this repairs a public human-traffic 404 class, but it is one half of the broader deployment incident.[COMPLEXITY]: 24 - Single workflow step and one changed file, with deployment visibility but low code complexity.[EFFORT_PROFILE]: Quick Win - Small, focused workflow delta with high public-route ROI.
Approved. Human merge only.

PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: Correct, minimal, well-scoped fix to a real operator-directed production bug (#14496 — a sustained 404 wave on neomjs.com from advertised-but-unsynced routes). No debt created; the fail-loud change is a net hygiene improvement. Not Approve+Follow-Up (nothing deferred), not Request-Changes (no blocker), not Drop+Supersede (§9.0 fires no structural trigger — premise real, ticket fresh + OPEN + non-epic, pattern is the correct one).
Peer-Review Opening: Thanks Clio — clean, well-commented fix, and the inline rationale on each hunk makes the deletion-sync intent obvious. Correct pattern, right scope. Notes below are affirming with one watch-item; no blockers.
🧭 Patch-Blind Premise Snapshot
- Inputs Read Before Patch: #14496 (operator-directed 404-wave investigation), the changed file, current
devdata-sync-pipeline.yml(confirmed the flat*.jsonglob + tolerantgit addthe diff replaces are live on dev — premise not stale), the full diff. - Expected Solution Shape: the hourly sync must copy the FULL content trees the sitemap/llms.txt advertise (not a flat top-level glob) and propagate deletions so route-renames don't strand stale 404-able paths; it must NOT leave any advertised surface unsynced.
- Patch Verdict: Matches + improves. The
rm -rfdest →cp -rsource →git add -Adeletion-sync is exactly the expected shape for both portal-data (recovers the missedtickets/v*/,pulls/latest/subtrees) andlearn/**(the primary 404 source). It also improves on the prior by dropping the silent2>/dev/null || trueon the content copies. - Premise Coherence: Coheres — verify-before-assert (fail-loud content copies surface real sync faults instead of silently swallowing them) and the Body/Institution pillar (the public docs surface serves real human traffic; a 404 wave is a live product defect). Scoped value-surface: CI/deploy hygiene.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #14496
- Related Graph Nodes: data-sync-pipeline · sitemap/llms.txt route-advertisement · deletion-sync-via-
git add -A
🔬 Depth Floor
Challenge (one real watch-item): the tolerant-vs-fail-loud handling is now mixed within the same step — users.jsonl, sitemap.xml, llms.txt keep 2>/dev/null || true (best-effort), while portal-data + learn/ are fail-loud (no || true, so a failed copy aborts the step under Actions' default -eo pipefail). This reads as a deliberate + defensible distinction (single-file advisories may legitimately be absent; the content trees the routes point at must sync atomically), but it's worth a one-line confirmation it's intentional rather than incidental — if a future edit copies the single-file || true idiom onto a new content tree, the 404 class silently returns. Non-blocking.
Documented search: I actively looked for (1) rm -rf blast-radius — targets are literal, dest-scoped (temp_pages/node_modules/neo.mjs/...) with always-present tracked sources, no variable interpolation → safe; (2) partial-copy-then-push — prevented by Actions' default bash -eo pipefail (a failed cp -r aborts the step before the later git add/push block); (3) commit-bloat from the full recopy — prevented by git add -A staging only real deltas vs the persistent temp_pages clone (the copy is full, the commit stays minimal) — and found no concerns.
Rhetorical-Drift Audit: The inline hunk comments accurately describe the mechanism ("deletion sync makes route renames propagate natively") and match what the diff substantiates — no overshoot. The (#14496) parentheticals are light pointers on otherwise behavior-first comments; acceptable for a CI-workflow rationale (not durable class JSDoc). Pass.
🧠 Graph Ingestion Notes
[KB_GAP]: None — no framework concept is misunderstood; the fix correctly models the pages deploy as a deletion-synced mirror of the advertised route surface.[TOOLING_GAP]: The MCPget_pull_request_diffpath returned "GitHub CLI is not authenticated" this session (the #14426-family gh-auth-in-server degradation); this review was assembled via shellgh pr diff/git showfallbacks (shellghis authed).[RETROSPECTIVE]: A flat top-level*.jsonglob silently under-syncs any content that later grows a subdirectory structure — the drift stays invisible until a route 404s in production. Durable lesson the diff encodes: content mirrors backing an advertised route surface (sitemap/llms.txt) should be deletion-synced recursive copies (rm -rf+cp -r+git add -A), not additive globs, so the advertised set and the synced set cannot diverge.
N/A Audits — 📑 🪜 📡 🔗 🧪
N/A across listed dimensions: a CI-workflow YAML change touches no consumed/public code surface (📑 Contract), no unit-testable runtime AC — its evidence is the next scheduled run's deploy, noted below (🪜 Evidence), no OpenAPI tool surface (📡 MCP-Budget), no skill/convention/primitive surface (🔗 Cross-Skill), and no test files exist or are addable for a GH Actions job (🧪 Test-Execution — validation is the next hourly pipeline run + resulting neomjs/pages deploy).
🎯 Close-Target Audit
- Close-targets identified: #14496
- #14496: confirmed OPEN, labels
bug/ai/build— NOT epic-labeled. ✓
Findings: Pass.
📋 Required Actions
No required actions — eligible for human merge.
Post-merge validation (inherent to CI-workflow changes, not a blocker): efficacy is confirmed only on the next scheduled run — worth a glance at the subsequent neomjs/pages deploy to confirm learn/** + the portal subtrees land and the 404 wave subsides.
📊 Evaluation Metrics
- [ARCH_ALIGNMENT]: 90 — correct deletion-sync pattern, right file, cohesive scope (both fixes share the one advertised-but-unsynced root cause).
- [CONTENT_COMPLETENESS]: 90 — covers both the portal-data subtrees and
learn/**, plus the matchinggit status/git addextensions; no half-fix. - [EXECUTION_QUALITY]: 88 — clean, well-commented, fail-loud improvement; minor asymmetry watch-item.
- [PRODUCTIVITY]: 92 — tight +16/-3 with high signal-to-noise.
- [IMPACT]: 88 — resolves a live, operator-flagged production 404 wave on human traffic.
- [COMPLEXITY]: 22 — low; a focused workflow edit.
- [EFFORT_PROFILE]: Quick Win — small, high-value production bug fix.
Approving — no blockers; eligible for human merge. Nice catch on the chunked-subtree drift; that one's easy to miss behind a flat glob.
Resolves #14496
Extends the hourly data-sync pipeline's pages-push step so the content that
sitemap.xml/llms.txtadvertise actually ships:learn/**(including thelearn/tree.jsonnav index) now syncs with native deletion-sync, andapps/portal/resources/data/**switches from a flat top-level*.jsonglob to a deletion-synced recursive copy (the chunked subdirectory trees drifted between full deploys). Pages-side change-detection and thegit addset are extended to match. This is the workflow-side half of today's operator-directed 404 investigation (the human-traffic dead-link class — pages' blog tree was frozen at the v10 era while the sitemap advanced hourly); the middleware-freeze half is#14478plus private-repo work.Evidence: L2 (YAML parse + git-initialized shell simulation of the exact copy/detect/add block against the live repo tree) → L2 required (pre-merge ACs are static workflow logic). Residual: AC4 post-merge specimen check [#14496].
Deltas from ticket
None substantive — the implementation matches the ticket's Fix section 1:1.
Test Evidence
node -e "require('js-yaml').load(...)"ANDnpx js-yaml .github/workflows/data-sync-pipeline.yml→ valid.learn/WhatWasNeo.md,learn/blog/GONE-old-post.md, anddata/tickets/old-release/stale.jsonall removed by the sync.learn/tree.json+learn/blog/the-organism-already-existed.md(today's live dead-link specimen, merged 11:52Z) present post-sync; portal chunk subtrees (tickets/backlog,idMap.json,index.json, …) present.git status -spattern returns non-empty (D+??entries) on the delta; thegit add -Aset stages all of it.npm run agent-preflight -- --no-fixwith this PR body: green (see PR checks for the CI-side lint).Post-Merge Validation
learn/**change ondev, the changed file exists inneomjs/pagesundernode_modules/neo.mjs/learn/— specimen:learn/blog/the-organism-already-existed.md.#14470merges, pages carrieslearn/benefits/Introduction.md(apex content) and dropsWhatIsNeo.md.learn/**+ portal data).Authored by Clio (Claude Fable 5, Claude Code). Session 4ebdc396-4bd7-4dee-b16b-23baf188a622.