Promote BSP Image Purpose Stage every Customize- and Build output into so it is ready for . This is the promote leg of Deploy — it copies files, never flashes and never builds. Prerequisites - Active target-platform profile with both and resolved (run and first). - initialized as a git repo (overlay tracker) with a clean working tree. - extracted from a BSP tarball + already run. - , , , and (for destinations) on the host. - + from (required when kernel-side repos have customize- commits). Overview This is the promote leg of Deploy — see for the pipeline view. The two channels this skill walk…

\\t'*}\n [ -f \"$src\" ] || {\n # refuse: \"Manifest entry references missing build output: $src.\n # Re-run /jetson-build-source.\"\n }\n done\nfi\n```\n\n## Diff-aware copy into bsp_image\n\nIterate the union of overlay files (paths relative to `$LFT_SRC`)\nand manifest entries (absolute `src` + relative `dst`). For each:\nif `bsp_image`'s copy is byte-identical, skip. Otherwise copy\nwith mode / owner / timestamp preserved. Use `sudo` only for\npaths under `rootfs/`, where the sample rootfs was extracted as\nroot and ownership must round-trip. Tag `INITRD_DIRTY=1` on any\n`rootfs/lib/modules/*` or `kernel/Image` write — the\n[\"Refresh initramfs\"](../SKILL.md#refresh-initramfs-when-kernel-or-modules-changed)\nstep gates on this flag.\n\n```bash\nCOPIED_OVERLAY=0; IDENTICAL_OVERLAY=0\nCOPIED_MANIFEST=0; IDENTICAL_MANIFEST=0\nFIRST=\"\"; LAST=\"\"\nINITRD_DIRTY=0 # set when kernel/Image or rootfs/lib/modules/* is copied\n\ncopy_one() {\n local src=\"$1\" dst=\"$2\" channel=\"$3\"\n\n if [ -f \"$dst\" ] && cmp -s \"$src\" \"$dst\"; then\n case \"$channel\" in\n overlay) IDENTICAL_OVERLAY=$((IDENTICAL_OVERLAY + 1));;\n manifest) IDENTICAL_MANIFEST=$((IDENTICAL_MANIFEST + 1));;\n esac\n return\n fi\n\n local rel=\"${dst#$LFT_DST/}\"\n case \"$rel\" in\n rootfs/*)\n sudo mkdir -p \"$(dirname \"$dst\")\"\n sudo cp -p \"$src\" \"$dst\"\n ;;\n *)\n mkdir -p \"$(dirname \"$dst\")\"\n cp -p \"$src\" \"$dst\"\n ;;\n esac\n\n case \"$rel\" in\n rootfs/lib/modules/*|kernel/Image) INITRD_DIRTY=1 ;;\n esac\n\n case \"$channel\" in\n overlay) COPIED_OVERLAY=$((COPIED_OVERLAY + 1));;\n manifest) COPIED_MANIFEST=$((COPIED_MANIFEST + 1));;\n esac\n [ -z \"$FIRST\" ] && FIRST=\"$rel\"\n LAST=\"$rel\"\n}\n\n# Channel A: overlay\nfor rel in \"${OVERLAY_FILES[@]}\"; do\n copy_one \"$LFT_SRC/$rel\" \"$LFT_DST/$rel\" overlay\ndone\n\n# Channel B: manifest\nfor line in \"${MANIFEST_ENTRIES[@]}\"; do\n src=${line%%

Promote BSP Image Purpose Stage every Customize- and Build output into so it is ready for . This is the promote leg of Deploy — it copies files, never flashes and never builds. Prerequisites - Active target-platform profile with both and resolved (run and first). - initialized as a git repo (overlay tracker) with a clean working tree. - extracted from a BSP tarball + already run. - , , , and (for destinations) on the host. - + from (required when kernel-side repos have customize- commits). Overview This is the promote leg of Deploy — see for the pipeline view. The two channels this skill walk…

\\t'*}\n dst_rel=${line##*

Promote BSP Image Purpose Stage every Customize- and Build output into so it is ready for . This is the promote leg of Deploy — it copies files, never flashes and never builds. Prerequisites - Active target-platform profile with both and resolved (run and first). - initialized as a git repo (overlay tracker) with a clean working tree. - extracted from a BSP tarball + already run. - , , , and (for destinations) on the host. - + from (required when kernel-side repos have customize- commits). Overview This is the promote leg of Deploy — see for the pipeline view. The two channels this skill walk…

\\t'}\n copy_one \"$src\" \"$LFT_DST/$dst_rel\" manifest\ndone\n```\n\nFail-fast: if any `cp` fails, surface the failed path and stop.\n`bsp_image` may be left partially updated — re-running after\nfixing the underlying issue (permission / disk) resumes\nnaturally because the loop is diff-aware and skips files\nalready copied.\n\n**Channel order.** Overlay first, then manifest. If the same\n`dst` appears in both (rare — an in-overlay hand-edit to a\nbinary that's also rebuilt), the manifest's copy wins — that's\nthe desired semantic, since the manifest represents the\nfreshly built artifact and the overlay copy is typically older\nstate.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":6684,"content_sha256":"e54addf0144b5178b7350142bd68dc80b4260e537d4da5a97dc7c22b3de8469c"},{"filename":"references/kernel-image-and-initramfs.md","content":"# Kernel `Image` mirror + initramfs refresh\n\nDetailed reference for the two procedure steps that keep\n`bsp_image`'s kernel and initramfs coherent after a kernel /\nmodule promote: [\"Mirror kernel Image into rootfs\"](../SKILL.md#mirror-kernel-image-into-rootfs-when-kernel-changed)\nand [\"Refresh initramfs\"](../SKILL.md#refresh-initramfs-when-kernel-or-modules-changed).\n\n## Why this matters\n\nTwo failure modes converge on the same fix:\n\n1. **Module shadowing.** The Jetson bootloader loads the initramfs\n **before** the NVMe rootfs is mounted and `pivot_root` runs.\n Any module that auto-loads during early boot — `pwm-tegra`,\n `nvgpu`, modules listed in `/etc/modules-load.d/`, modules\n pulled in by udev uevents on platform-bus enumeration — comes\n from the initramfs copy. Once a module is live in the kernel,\n the rootfs copy at `/lib/modules/\u003cver>/` **cannot** replace it\n (you cannot overwrite a loaded module). The rebuilt initramfs\n must carry the customized modules in place from boot one.\n2. **Symbol-version / vermagic skew.** A kernel `Image` rebuild\n changes the kernel's exported symbol versions (and may shift\n internal layouts) even when `UTS_RELEASE` stays the same. The\n modules in the stale initramfs were built against the\n *previous* kernel and will be rejected at load time with\n \"disagrees about version of symbol X\", or worse silently bind\n to a different ABI. Rebuilding the initramfs from the rootfs's\n freshly built `/lib/modules/\u003cver>/` keeps the on-disk modules\n in lockstep with the kernel they have to load into.\n\nBoth modes are closed by the same gate on `kernel/Image` or\n`rootfs/lib/modules/*`. Below is why the mirror step is required\n*alongside* the refresh.\n\n## Mirror semantics — kernel `Image` lands in two places\n\nThe kernel `Image` lives in two paths inside `bsp_image`:\n\n- `\u003cLFT_DST>/kernel/Image` — read by the flash tool, written to\n the kernel-DTB / boot partition the bootloader actually loads.\n- `\u003cLFT_DST>/rootfs/boot/Image` — the copy that lives inside the\n flashed rootfs (visible as `/boot/Image` on the booted DUT, and\n visible as `/boot/Image` from inside any chroot rooted at\n `rootfs/`).\n\nThe build manifest only carries the `kernel/Image` dst (build\noutput goes to one canonical destination per artifact). Without\nthe mirror, the next step (`l4t_update_initrd.sh`) chroots into\n`rootfs/` and runs `nv-update-initrd`, which resolves the kernel\nvia `/boot/Image` (= `rootfs/boot/Image`) — i.e. the **stale**\ncopy — and would build the initramfs against the previous\nkernel's symbol table even though we just promoted a new one.\nFlashing the resulting image leaves the DUT with a fresh\n`kernel/Image` paired with stale-vermagic modules baked into the\ninitramfs.\n\n### Mirror snippet\n\nMirror immediately after the diff-aware copy, before invoking the\nrefresh tool. Diff-aware: skip if already byte-identical (the\nflash tool may have synced them on a prior run; rerunning is a\nno-op).\n\n```bash\nKIMG_SRC=\"$LFT_DST/kernel/Image\"\nKIMG_DST=\"$LFT_DST/rootfs/boot/Image\"\nKIMG_MIRRORED=\"skipped (already identical or kernel/Image absent)\"\nif [ -f \"$KIMG_SRC\" ]; then\n if ! [ -f \"$KIMG_DST\" ] || ! cmp -s \"$KIMG_SRC\" \"$KIMG_DST\"; then\n sudo cp -p \"$KIMG_SRC\" \"$KIMG_DST\"\n KIMG_MIRRORED=\"copied $KIMG_SRC -> $KIMG_DST\"\n INITRD_DIRTY=1 # mirror is a write under rootfs/; refresh now mandatory\n fi\nfi\n```\n\nThe `INITRD_DIRTY=1` set here covers the corner case where the\nmanifest carried only `kernel/Image` (no `rootfs/lib/modules/*`\nentries — e.g. an obj-y-only kernel edit) and `copy_one` never\nflipped the flag. After this step, `INITRD_DIRTY=1` iff either\nthe kernel binary or any module changed in the rootfs.\n\n## Refresh tool — `l4t_update_initrd.sh`\n\n`tools/l4t_update_initrd.sh` ships inside every Linux_for_Tegra\ntree. It rebuilds the initramfs by chrooting into\n`\u003cLFT_DST>/rootfs/`, running NVIDIA's `nv-update-initrd` inside\nit, then copying the result to **both**\n`\u003cLFT_DST>/bootloader/l4t_initrd.img` (the bootloader-side base\nused by the flash tool) and `\u003cLFT_DST>/rootfs/boot/initrd` (the\nrootfs copy).\n\n### Refresh snippet\n\n```bash\nif [ \"$INITRD_DIRTY\" = 1 ]; then\n [ -x \"$LFT_DST/tools/l4t_update_initrd.sh\" ] || {\n # refuse: \"tool not found at\n # $LFT_DST/tools/l4t_update_initrd.sh; re-run /jetson-init-image\n # to repopulate Linux_for_Tegra/tools/.\"\n }\n ( cd \"$LFT_DST\" && sudo ./tools/l4t_update_initrd.sh ) || {\n # refuse: \"l4t_update_initrd.sh exited non-zero;\n # bsp_image initrd is in indeterminate state. Re-run promote\n # after fixing the underlying cause.\"\n }\n INITRD_STATUS=\"rebuilt\"\nelse\n INITRD_STATUS=\"skipped (no kernel/Image or rootfs/lib/modules/ changes)\"\nfi\n```\n\n### Outputs (when the tool runs)\n\n- `\u003cLFT_DST>/bootloader/l4t_initrd.img` — the base image used by\n the flash tool to populate the bootloader-side initramfs (lands\n in the kernel-DTB / boot partition at flash time, depending on\n the carrier).\n- `\u003cLFT_DST>/rootfs/boot/initrd` — becomes `/boot/initrd` on the\n booted DUT.\n\n(Note: `\u003cLFT_DST>/bootloader/initrd` is a separate, pre-staged\nfile used during the initrd-flash boot sequence — it is **not**\ntouched by this step; `l4t_initrd_flash.sh` regenerates / consumes\nit independently.)\n\n### Skip behavior\n\nSkip the entire step when `INITRD_DIRTY=0` (typical for\noverlay-only edits like `nvfancontrol.conf` / `nvpmodel.conf` /\nBPMP DTB / MB1 PMIC BCT — none of which touch the kernel `Image`\nor `rootfs/lib/modules/`).\n\nThe tool is idempotent: rerunning after a no-op promote produces\nbyte-identical initrd files. Typical runtime: ~30 s.\n\n### Out-of-scope workarounds\n\nDUT-side workarounds (e.g. `update-initramfs -u` + manual `cp` of\n`/boot/initrd.img-\u003cver>` over `/boot/initrd`) are explicitly out\nof scope here — fix the gap at promote time so flash ships a\ncoherent image. The static + on-target checks in\n[`../jetson-validate-image/SKILL.md`](../../jetson-validate-image/SKILL.md)\ncatch drift if it ever re-appears.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":6011,"content_sha256":"6f5edf7377e04157515f03046a9f79064c2077e541a3e10d976f28467d8b0b3b"},{"filename":"skill-card.md","content":"## Description: \u003cbr>\nUse to promote overlay files and built artifacts into the staged BSP image. \u003cbr>\n\nThis skill is ready for commercial/non-commercial use. \u003cbr>\n\n## Owner\nNVIDIA \u003cbr>\n\n### License/Terms of Use: \u003cbr>\nCC-BY-4.0 AND Apache 2.0 \u003cbr>\n## Use Case: \u003cbr>\nDevelopers and engineers use this skill to promote customized overlay files and rebuilt kernel, module, and device-tree artifacts into a staged Jetson Linux BSP image prior to flashing. \u003cbr>\n\n### Deployment Geography for Use: \u003cbr>\nGlobal \u003cbr>\n\n## Known Risks and Mitigations: \u003cbr>\nRisk: Review before execution as proposals could introduce incorrect or misleading guidance into skills. \u003cbr>\nMitigation: Review and scan skill before deployment. \u003cbr>\n\n## Reference(s): \u003cbr>\n- [Build-Source Freshness Gate](references/build-source-freshness-gate.md) \u003cbr>\n- [Copy-Pass Snippets](references/copy-pass-snippets.md) \u003cbr>\n- [Kernel Image and Initramfs](references/kernel-image-and-initramfs.md) \u003cbr>\n\n\n## Skill Output: \u003cbr>\n**Output Type(s):** [Shell commands, Configuration instructions] \u003cbr>\n**Output Format:** [Markdown with inline bash code blocks] \u003cbr>\n**Output Parameters:** [1D] \u003cbr>\n**Other Properties Related to Output:** [None] \u003cbr>\n\n## Evaluation Agents Used: \u003cbr>\n- claude-code \u003cbr>\n- codex \u003cbr>\n\n\n\n## Evaluation Tasks: \u003cbr>\nEvaluated against 2 internal evaluation tasks (2 positive skill-activation cases). \u003cbr>\n\n## Evaluation Metrics Used: \u003cbr>\nReported benchmark dimensions: \u003cbr>\n- Security: Checks whether skill-assisted execution avoids unsafe behavior such as secret leakage, destructive commands, or unauthorized access. \u003cbr>\n- Correctness: Checks whether the agent follows the expected workflow and produces the correct final output. \u003cbr>\n- Discoverability: Checks whether the agent loads the skill when relevant and avoids using it when irrelevant. \u003cbr>\n- Effectiveness: Checks whether the agent performs measurably better with the skill than without it. \u003cbr>\n- Efficiency: Checks whether the agent uses fewer tokens and avoids redundant work. \u003cbr>\n\nUnderlying evaluation signals used in this run: \u003cbr>\n- `security`: Checks for unsafe operations, secret leakage, and unauthorized access. \u003cbr>\n- `skill_execution`: Verifies that the agent loaded the expected skill and workflow. \u003cbr>\n- `skill_efficiency`: Checks routing quality, decoy avoidance, and redundant tool usage. \u003cbr>\n- `accuracy`: Grades final-answer correctness against the reference answer. \u003cbr>\n- `goal_accuracy`: Checks whether the overall user task completed successfully. \u003cbr>\n- `behavior_check`: Verifies expected behavior steps, including safety expectations. \u003cbr>\n- `token_efficiency`: Compares token usage with and without the skill. \u003cbr>\n\n\n\n## Evaluation Results: \u003cbr>\n| Dimension | Num | `claude-code` | `codex` |\n|---|---:|---:|---:|\n| Security | 2 | 100% (+0%) | 100% (+0%) |\n| Correctness | 2 | 82% (+82%) | 81% (+31%) |\n| Discoverability | 2 | 73% (+73%) | 88% (+32%) |\n| Effectiveness | 2 | 53% (+53%) | 56% (+38%) |\n| Efficiency | 2 | 66% (+39%) | 82% (+32%) |\n\n## Skill Version(s): \u003cbr>\n0.0.1 (source: frontmatter) \u003cbr>\n\n## Ethical Considerations: \u003cbr>\nNVIDIA believes Trustworthy AI is a shared responsibility and we have established policies and practices to enable development for a wide array of AI applications. When downloaded or used in accordance with our terms of service, developers should work with their internal team to ensure this skill meets requirements for the relevant industry and use case and addresses unforeseen product misuse. \u003cbr>\n\n(For Release on NVIDIA Platforms Only) \u003cbr>\nPlease report quality, risk, security vulnerabilities or NVIDIA AI Concerns [here](https://app.intigriti.com/programs/nvidia/nvidiavdp/detail). \u003cbr>\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3706,"content_sha256":"bc63961ef38e7f4381e43aeb38bea3fb242fea100178920acc0629649bb68e06"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"Promote BSP Image","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Purpose","type":"text"}]},{"type":"paragraph","content":[{"text":"Stage every Customize-* and Build output into ","type":"text"},{"text":"bsp_image","type":"text","marks":[{"type":"code_inline"}]},{"text":" so it is ready for ","type":"text"},{"text":"/jetson-flash-image","type":"text","marks":[{"type":"code_inline"}]},{"text":". This is the ","type":"text"},{"text":"promote leg of Deploy","type":"text","marks":[{"type":"strong"}]},{"text":" — it copies files, never flashes and never builds.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Prerequisites","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Active target-platform profile with both ","type":"text"},{"text":"source:","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":"bsp_image:","type":"text","marks":[{"type":"code_inline"}]},{"text":" resolved (run ","type":"text"},{"text":"/jetson-init-source","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":"/jetson-init-image","type":"text","marks":[{"type":"code_inline"}]},{"text":" first).","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\u003csource.root_path>/Linux_for_Tegra/","type":"text","marks":[{"type":"code_inline"}]},{"text":" initialized as a git repo (overlay tracker) with a clean working tree.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\u003cbsp_image.root_path>/Linux_for_Tegra/","type":"text","marks":[{"type":"code_inline"}]},{"text":" extracted from a BSP tarball + ","type":"text"},{"text":"apply_binaries.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":" already run.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"git","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"yq","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"cmp","type":"text","marks":[{"type":"code_inline"}]},{"text":", and ","type":"text"},{"text":"sudo","type":"text","marks":[{"type":"code_inline"}]},{"text":" (for ","type":"text"},{"text":"rootfs/*","type":"text","marks":[{"type":"code_inline"}]},{"text":" destinations) on the host.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\u003csource.root_path>/.build-manifest.yaml","type":"text","marks":[{"type":"code_inline"}]},{"text":" + ","type":"text"},{"text":".build-state.yaml","type":"text","marks":[{"type":"code_inline"}]},{"text":" from ","type":"text"},{"text":"/jetson-build-source","type":"text","marks":[{"type":"code_inline"}]},{"text":" (required when kernel-side repos have customize-* commits).","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Overview","type":"text"}]},{"type":"paragraph","content":[{"text":"This is the ","type":"text"},{"text":"promote leg of Deploy","type":"text","marks":[{"type":"strong"}]},{"text":" — see ","type":"text"},{"text":"../../context/bsp-customization-workflow.md","type":"text","marks":[{"type":"link","attrs":{"href":"../../context/bsp-customization-workflow.md","title":null}},{"type":"code_inline"}]},{"text":" for the pipeline view. The two channels this skill walks are:","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Channel","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Source","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Carrier","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Owner","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Overlay tracker","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\u003csource.root_path>/Linux_for_Tegra/","type":"text","marks":[{"type":"code_inline"}]},{"text":" (git repo at HEAD)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Customize-* outputs that don't require a build (e.g. ","type":"text"},{"text":"nvfancontrol.conf","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"nvpmodel.conf","type":"text","marks":[{"type":"code_inline"}]},{"text":", BPMP DTB hand-edits)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Customize ","type":"text"},{"text":"customize-*","type":"text","marks":[{"type":"code_inline"}]},{"text":" skills commit here","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Build manifest","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\u003csource.root_path>/.build-manifest.yaml","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Rebuilt kernel ","type":"text"},{"text":"Image","type":"text","marks":[{"type":"code_inline"}]},{"text":", in-tree ","type":"text"},{"text":".ko","type":"text","marks":[{"type":"code_inline"}]},{"text":", OOT ","type":"text"},{"text":".ko","type":"text","marks":[{"type":"code_inline"}]},{"text":", NVIDIA DTBs","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Build ","type":"text"},{"text":"jetson-build-source","type":"text","marks":[{"type":"link","attrs":{"href":"../jetson-build-source/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" writes here","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"The skill computes the union of files to copy and writes each into ","type":"text"},{"text":"\u003cbsp_image.root_path>/Linux_for_Tegra/","type":"text","marks":[{"type":"code_inline"}]},{"text":" with diff-aware skip-if-identical logic. When the copy pass touches the kernel ","type":"text"},{"text":"Image","type":"text","marks":[{"type":"code_inline"}]},{"text":" or anything under ","type":"text"},{"text":"rootfs/lib/modules/","type":"text","marks":[{"type":"code_inline"}]},{"text":", it also rebuilds the initramfs via NVIDIA's ","type":"text"},{"text":"tools/l4t_update_initrd.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":" so the freshly promoted kernel + modules ship in the initrd the bootloader actually loads. After it returns, ","type":"text"},{"text":"bsp_image","type":"text","marks":[{"type":"code_inline"}]},{"text":" carries every Customize and Build output. The skill does ","type":"text"},{"text":"not","type":"text","marks":[{"type":"strong"}]},{"text":" flash and does ","type":"text"},{"text":"not","type":"text","marks":[{"type":"strong"}]},{"text":" modify the workspace.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"When to invoke","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"First leg of the typical Deploy chain ","type":"text"},{"text":"jetson-promote-image → jetson-flash-image → jetson-validate-image","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Standalone, when the user wants ","type":"text"},{"text":"bsp_image","type":"text","marks":[{"type":"code_inline"}]},{"text":" updated but isn't ready to flash yet (e.g. to inspect resolved files, run an out-of-band build that reads bsp_image, or hand bsp_image to a separate flashing host).","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Procedure","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Resolve active target + paths","type":"text"}]},{"type":"paragraph","content":[{"text":"Resolve the active profile per the contract in ","type":"text"},{"text":"../../context/target-platform-contract.md","type":"text","marks":[{"type":"link","attrs":{"href":"../../context/target-platform-contract.md","title":null}},{"type":"code_inline"}]},{"text":".","type":"text"}]},{"type":"paragraph","content":[{"text":"Refuse and route in these cases:","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Condition","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Refuse with","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"No active profile, or ","type":"text"},{"text":"active: NA","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Route to ","type":"text"},{"text":"/jetson-set-target","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"/jetson-init-target","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Profile lacks ","type":"text"},{"text":"bsp_image:","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Route to ","type":"text"},{"text":"/jetson-init-image","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\u003cbsp_image.root_path>/Linux_for_Tegra/","type":"text","marks":[{"type":"code_inline"}]},{"text":" missing","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Route to ","type":"text"},{"text":"/jetson-init-image","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\u003csource.root_path>/Linux_for_Tegra/","type":"text","marks":[{"type":"code_inline"}]},{"text":" missing or not a git repo","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Route to ","type":"text"},{"text":"/jetson-init-source","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"Resolve paths:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\u003cworkspace>","type":"text","marks":[{"type":"code_inline"}]},{"text":" = parent of the active profile's ","type":"text"},{"text":"target-platform/","type":"text","marks":[{"type":"code_inline"}]},{"text":" directory (discovered at load time).","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\u003cbsp_image.root_path>","type":"text","marks":[{"type":"code_inline"}]},{"text":" from ","type":"text"},{"text":"bsp_image.root_path:","type":"text","marks":[{"type":"code_inline"}]},{"text":" if present, else ","type":"text"},{"text":"\u003cworkspace>/Image","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\u003csource.root_path>","type":"text","marks":[{"type":"code_inline"}]},{"text":" from ","type":"text"},{"text":"source.root_path:","type":"text","marks":[{"type":"code_inline"}]},{"text":" if present, else ","type":"text"},{"text":"\u003cworkspace>/Source","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Bind shell variables for the rest of the procedure:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"LFT_SRC=\"\u003csource.root_path>/Linux_for_Tegra\" # overlay tracker\nLFT_DST=\"\u003cbsp_image.root_path>/Linux_for_Tegra\"\nMANIFEST=\"\u003csource.root_path>/.build-manifest.yaml\" # build outputs","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Validate the two channels","type":"text"}]},{"type":"paragraph","content":[{"text":"The skill needs at least one channel populated. Refuse if the overlay tracker has uncommitted changes (","type":"text"},{"text":"status --porcelain","type":"text","marks":[{"type":"code_inline"}]},{"text":" non-empty), if ","type":"text"},{"text":"$MANIFEST","type":"text","marks":[{"type":"code_inline"}]},{"text":" exists but doesn't parse as YAML, or if both channels are empty. Records ","type":"text"},{"text":"OVERLAY_HAS_COMMITS","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":"OVERLAY_HEAD","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":"MANIFEST_PRESENT","type":"text","marks":[{"type":"code_inline"}]},{"text":" for downstream steps.","type":"text"}]},{"type":"paragraph","content":[{"text":"See ","type":"text"},{"text":"references/copy-pass-snippets.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/copy-pass-snippets.md#validate-the-two-channels","title":null}},{"type":"code_inline"}]},{"text":" for the shell snippet and refuse messages.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Verify build-source freshness","type":"text"}]},{"type":"paragraph","content":[{"text":"Refuse if ","type":"text"},{"text":".build-state.yaml","type":"text","marks":[{"type":"code_inline"}]},{"text":" shows any kernel-side repo in ","type":"text"},{"text":"Source/bsp_sources/","type":"text","marks":[{"type":"code_inline"}]},{"text":" dirty since the last ","type":"text"},{"text":"/jetson-build-source","type":"text","marks":[{"type":"code_inline"}]},{"text":" — otherwise the copy pass would silently ship stale artifacts. Detection rules + shell snippet in ","type":"text"},{"text":"references/build-source-freshness-gate.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/build-source-freshness-gate.md","title":null}},{"type":"code_inline"}]},{"text":". Records ","type":"text"},{"text":"BUILD_FRESH=1","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Pre-promote collision check (overlay only)","type":"text"}]},{"type":"paragraph","content":[{"text":"When the overlay tracks a remote, refuse if upstream has commits not yet pulled. Skip gracefully when no remote is configured (the default ","type":"text"},{"text":"git init","type":"text","marks":[{"type":"code_inline"}]},{"text":" empty tracker from ","type":"text"},{"text":"jetson-init-source","type":"text","marks":[{"type":"code_inline"}]},{"text":"). Manifest channel has no git remote concept — this check is overlay-only. Records ","type":"text"},{"text":"COLLISION_CHECK","type":"text","marks":[{"type":"code_inline"}]},{"text":" for the Summary.","type":"text"}]},{"type":"paragraph","content":[{"text":"See ","type":"text"},{"text":"references/copy-pass-snippets.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/copy-pass-snippets.md#pre-promote-collision-check-overlay-only","title":null}},{"type":"code_inline"}]},{"text":" for the shell snippet.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Enumerate sources (both channels)","type":"text"}]},{"type":"paragraph","content":[{"text":"Channel A — overlay","type":"text","marks":[{"type":"strong"}]},{"text":": ","type":"text"},{"text":"git ls-files","type":"text","marks":[{"type":"code_inline"}]},{"text":" against ","type":"text"},{"text":"$LFT_SRC","type":"text","marks":[{"type":"code_inline"}]},{"text":" is the source of truth (transparent to symlink mounts when ","type":"text"},{"text":"source.repos.Linux_for_Tegra","type":"text","marks":[{"type":"code_inline"}]},{"text":" was overridden, excludes untracked / ","type":"text"},{"text":".gitignore","type":"text","marks":[{"type":"code_inline"}]},{"text":"d files). Each entry maps ","type":"text"},{"text":"src = $LFT_SRC/\u003crel>","type":"text","marks":[{"type":"code_inline"}]},{"text":" → ","type":"text"},{"text":"dst = $LFT_DST/\u003crel>","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]},{"type":"paragraph","content":[{"text":"Channel B — manifest","type":"text","marks":[{"type":"strong"}]},{"text":": parse ","type":"text"},{"text":"artifacts[].{src,dst}","type":"text","marks":[{"type":"code_inline"}]},{"text":" from ","type":"text"},{"text":"$MANIFEST","type":"text","marks":[{"type":"code_inline"}]},{"text":". Refuse if any ","type":"text"},{"text":"src","type":"text","marks":[{"type":"code_inline"}]},{"text":" is missing on disk (build was interrupted, or manifest stale — re-run ","type":"text"},{"text":"/jetson-build-source","type":"text","marks":[{"type":"code_inline"}]},{"text":"). The manifest schema is written by ","type":"text"},{"text":"jetson-build-source","type":"text","marks":[{"type":"link","attrs":{"href":"../jetson-build-source/references/manifest-schema.md","title":null}},{"type":"code_inline"}]},{"text":" v0.2.0","type":"text","marks":[{"type":"link","attrs":{"href":"../jetson-build-source/references/manifest-schema.md","title":null}}]},{"text":".","type":"text"}]},{"type":"paragraph","content":[{"text":"See ","type":"text"},{"text":"references/copy-pass-snippets.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/copy-pass-snippets.md#enumerate-sources","title":null}},{"type":"code_inline"}]},{"text":" for both shell snippets and the manifest YAML schema.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Diff-aware copy into bsp_image","type":"text"}]},{"type":"paragraph","content":[{"text":"Iterate the union of overlay files and manifest entries. For each ","type":"text"},{"text":"dst","type":"text","marks":[{"type":"code_inline"}]},{"text":": if byte-identical, skip; otherwise ","type":"text"},{"text":"cp -p","type":"text","marks":[{"type":"code_inline"}]},{"text":" (with ","type":"text"},{"text":"sudo","type":"text","marks":[{"type":"code_inline"}]},{"text":" for ","type":"text"},{"text":"rootfs/*","type":"text","marks":[{"type":"code_inline"}]},{"text":" destinations, where the sample rootfs was extracted as root). Tag ","type":"text"},{"text":"INITRD_DIRTY=1","type":"text","marks":[{"type":"code_inline"}]},{"text":" on any ","type":"text"},{"text":"rootfs/lib/modules/*","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"kernel/Image","type":"text","marks":[{"type":"code_inline"}]},{"text":" write — the \"Refresh initramfs\" step gates on this flag. Counts / ","type":"text"},{"text":"FIRST","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":"LAST","type":"text","marks":[{"type":"code_inline"}]},{"text":" are recorded for the Summary.","type":"text"}]},{"type":"paragraph","content":[{"text":"Fail-fast: if any ","type":"text"},{"text":"cp","type":"text","marks":[{"type":"code_inline"}]},{"text":" fails, surface the failed path and stop. ","type":"text"},{"text":"bsp_image","type":"text","marks":[{"type":"code_inline"}]},{"text":" may be left partially updated — re-running after fixing the cause resumes via the diff-aware skip. ","type":"text"},{"text":"Channel order","type":"text","marks":[{"type":"strong"}]},{"text":" is overlay first, then manifest: on a ","type":"text"},{"text":"dst","type":"text","marks":[{"type":"code_inline"}]},{"text":" collision the manifest wins (freshly built artifact beats the older overlay copy).","type":"text"}]},{"type":"paragraph","content":[{"text":"See ","type":"text"},{"text":"references/copy-pass-snippets.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/copy-pass-snippets.md#diff-aware-copy-into-bsp_image","title":null}},{"type":"code_inline"}]},{"text":" for the ","type":"text"},{"text":"copy_one()","type":"text","marks":[{"type":"code_inline"}]},{"text":" function and the two driving loops.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Mirror kernel Image into rootfs (when kernel changed)","type":"text"}]},{"type":"paragraph","content":[{"text":"The kernel ","type":"text"},{"text":"Image","type":"text","marks":[{"type":"code_inline"}]},{"text":" lives in two paths inside ","type":"text"},{"text":"bsp_image","type":"text","marks":[{"type":"code_inline"}]},{"text":": ","type":"text"},{"text":"\u003cLFT_DST>/kernel/Image","type":"text","marks":[{"type":"code_inline"}]},{"text":" (read by the flash tool) and ","type":"text"},{"text":"\u003cLFT_DST>/rootfs/boot/Image","type":"text","marks":[{"type":"code_inline"}]},{"text":" (the rootfs-side copy, visible as ","type":"text"},{"text":"/boot/Image","type":"text","marks":[{"type":"code_inline"}]},{"text":" from inside the rootfs chroot the refresh tool will run in). The build manifest only carries the ","type":"text"},{"text":"kernel/Image","type":"text","marks":[{"type":"code_inline"}]},{"text":" dst, so this step mirrors ","type":"text"},{"text":"kernel/Image","type":"text","marks":[{"type":"code_inline"}]},{"text":" → ","type":"text"},{"text":"rootfs/boot/Image","type":"text","marks":[{"type":"code_inline"}]},{"text":" (diff-aware, no-op when already in sync) so the chrooted refresh tool resolves the kernel against the freshly promoted binary, not the stale rootfs copy. The mirror also sets ","type":"text"},{"text":"INITRD_DIRTY=1","type":"text","marks":[{"type":"code_inline"}]},{"text":" so a kernel-only promote (no ","type":"text"},{"text":"rootfs/lib/modules/*","type":"text","marks":[{"type":"code_inline"}]},{"text":" writes) still triggers the refresh.","type":"text"}]},{"type":"paragraph","content":[{"text":"See ","type":"text"},{"text":"references/kernel-image-and-initramfs.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/kernel-image-and-initramfs.md#mirror-semantics--kernel-image-lands-in-two-places","title":null}},{"type":"code_inline"}]},{"text":" for the shell snippet, the failure mode this prevents, and the ","type":"text"},{"text":"INITRD_DIRTY","type":"text","marks":[{"type":"code_inline"}]},{"text":" corner case.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Refresh initramfs (when kernel or modules changed)","type":"text"}]},{"type":"paragraph","content":[{"text":"Run ","type":"text"},{"text":"tools/l4t_update_initrd.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":" from ","type":"text"},{"text":"\u003cLFT_DST>/","type":"text","marks":[{"type":"code_inline"}]},{"text":" whenever ","type":"text"},{"text":"INITRD_DIRTY=1","type":"text","marks":[{"type":"code_inline"}]},{"text":" (set by the diff-aware copy or the mirror step above). The tool chroots into ","type":"text"},{"text":"rootfs/","type":"text","marks":[{"type":"code_inline"}]},{"text":", runs NVIDIA's ","type":"text"},{"text":"nv-update-initrd","type":"text","marks":[{"type":"code_inline"}]},{"text":", and writes both ","type":"text"},{"text":"\u003cLFT_DST>/bootloader/l4t_initrd.img","type":"text","marks":[{"type":"code_inline"}]},{"text":" (used by the flash tool) and ","type":"text"},{"text":"\u003cLFT_DST>/rootfs/boot/initrd","type":"text","marks":[{"type":"code_inline"}]},{"text":" (","type":"text"},{"text":"/boot/initrd","type":"text","marks":[{"type":"code_inline"}]},{"text":" on the DUT). Idempotent; ~30 s. Skip when ","type":"text"},{"text":"INITRD_DIRTY=0","type":"text","marks":[{"type":"code_inline"}]},{"text":" (overlay-only edits). DUT-side workarounds (","type":"text"},{"text":"update-initramfs -u","type":"text","marks":[{"type":"code_inline"}]},{"text":" + manual ","type":"text"},{"text":"cp","type":"text","marks":[{"type":"code_inline"}]},{"text":") are out of scope — fix the gap here so flash ships a coherent image.","type":"text"}]},{"type":"paragraph","content":[{"text":"See ","type":"text"},{"text":"references/kernel-image-and-initramfs.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/kernel-image-and-initramfs.md#refresh-tool--l4t_update_initrdsh","title":null}},{"type":"code_inline"}]},{"text":" for the shell snippet, refuse paths, the \"module shadowing\" and \"vermagic skew\" failure modes the rebuild closes, and why ","type":"text"},{"text":"bootloader/initrd","type":"text","marks":[{"type":"code_inline"}]},{"text":" (a different file) is left alone.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Summary","type":"text"}]},{"type":"paragraph","content":[{"text":"Report:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Overlay scope: ","type":"text"},{"text":"overlay HEAD ($OVERLAY_HEAD)","type":"text","marks":[{"type":"code_inline"}]},{"text":" or \"(empty)\".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Manifest scope: ","type":"text"},{"text":"mode=\u003c...>, bsp_version=\u003c...>, rebuilt_at=\u003c...>, N artifacts","type":"text","marks":[{"type":"code_inline"}]},{"text":" or \"(absent)\".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Collision check: ","type":"text"},{"text":"$COLLISION_CHECK","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Counts:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"overlay: ","type":"text"},{"text":"$COPIED_OVERLAY copied, $IDENTICAL_OVERLAY identical","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"manifest: ","type":"text"},{"text":"$COPIED_MANIFEST copied, $IDENTICAL_MANIFEST identical","type":"text","marks":[{"type":"code_inline"}]}]}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Kernel Image mirror: ","type":"text"},{"text":"$KIMG_MIRRORED","type":"text","marks":[{"type":"code_inline"}]},{"text":" and initramfs: ","type":"text"},{"text":"$INITRD_STATUS","type":"text","marks":[{"type":"code_inline"}]},{"text":" (","type":"text"},{"text":"copied …","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":"rebuilt","type":"text","marks":[{"type":"code_inline"}]},{"text":" when triggered by ","type":"text"},{"text":"kernel/Image","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"rootfs/lib/modules/*","type":"text","marks":[{"type":"code_inline"}]},{"text":" writes; ","type":"text"},{"text":"skipped …","type":"text","marks":[{"type":"code_inline"}]},{"text":" otherwise).","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"First / last paths copied (omit if both ","type":"text"},{"text":"COPIED","type":"text","marks":[{"type":"code_inline"}]},{"text":" totals are 0).","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Resolved ","type":"text"},{"text":"\u003csource.root_path>","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\u003cbsp_image.root_path>","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Next step: ","type":"text"},{"text":"/jetson-flash-image","type":"text","marks":[{"type":"code_inline"}]},{"text":" (or ","type":"text"},{"text":"/jetson-validate-image","type":"text","marks":[{"type":"code_inline"}]},{"text":" if the user only wanted bsp_image refreshed for inspection / static validation).","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Limitations","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Two channels, one destination.","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"bsp_image/Linux_for_Tegra/","type":"text","marks":[{"type":"code_inline"}]},{"text":" is written by both passes. Overlay carries customize-* outputs (overlay-only edits like nvfancontrol.conf); manifest carries rebuilt binaries (kernel/OOT/DT). The two are intentionally disjoint by construction: build outputs don't go into the overlay, and customize-* edits to non-build files don't enter the manifest.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Build manifest is the trace-to-dirty contract.","type":"text","marks":[{"type":"strong"}]},{"text":" Anything in the manifest came from a dirty source repo (per ","type":"text"},{"text":"jetson-build-source","type":"text","marks":[{"type":"code_inline"}]},{"text":"'s \"Write the build manifest\" step trace policy). Promoting the manifest is therefore safe: every entry is a customization-bearing artifact, not toolchain-divergence noise. The skill does not re-derive the trace — it trusts the manifest.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Manifest entries can outlive their build outputs.","type":"text","marks":[{"type":"strong"}]},{"text":" If the user wipes ","type":"text"},{"text":"Source/.build/","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"bsp_sources/","type":"text","marks":[{"type":"code_inline"}]},{"text":"'s build artifacts between ","type":"text"},{"text":"jetson-build-source","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":"jetson-promote-image","type":"text","marks":[{"type":"code_inline"}]},{"text":", the manifest will reference missing files. The \"Enumerate sources (both channels)\" step refuses in that case and points the user at ","type":"text"},{"text":"/jetson-build-source","type":"text","marks":[{"type":"code_inline"}]},{"text":" to rebuild.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Manifest absence is fine when only overlay edits happened.","type":"text","marks":[{"type":"strong"}]},{"text":" A purely overlay-side customization (e.g. ","type":"text"},{"text":"customize-fan","type":"text","marks":[{"type":"code_inline"}]},{"text":") produces no build outputs and writes no manifest — the \"Enumerate sources (both channels)\" step is a no-op, the \"Diff-aware copy into bsp_image\" step promotes only overlay files. The skill prints \"manifest: (absent)\" in the summary and continues.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Diff-aware, idempotent.","type":"text","marks":[{"type":"strong"}]},{"text":" Re-running with no overlay commits or manifest changes since the last promote is a no-op (all files identical). Use this to confirm bsp_image is in sync without side effects.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Symlink-mount transparency.","type":"text","marks":[{"type":"strong"}]},{"text":" When ","type":"text"},{"text":"source.repos.Linux_for_Tegra","type":"text","marks":[{"type":"code_inline"}]},{"text":" was overridden in ","type":"text"},{"text":"jetson-init-source","type":"text","marks":[{"type":"code_inline"}]},{"text":", the canonical mount is a symlink into ","type":"text"},{"text":"\u003csource.root_path>/.repos/Linux_for_Tegra/\u003csubdir>","type":"text","marks":[{"type":"code_inline"}]},{"text":". ","type":"text"},{"text":"git -C","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"cp -p","type":"text","marks":[{"type":"code_inline"}]},{"text":", and ","type":"text"},{"text":"cmp -s","type":"text","marks":[{"type":"code_inline"}]},{"text":" all follow it transparently — no special handling needed at this layer. Manifest ","type":"text"},{"text":"src","type":"text","marks":[{"type":"code_inline"}]},{"text":" paths are absolute, so symlinks under ","type":"text"},{"text":"bsp_sources/","type":"text","marks":[{"type":"code_inline"}]},{"text":" don't matter for the manifest channel.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"sudo","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" is scoped to ","type":"text","marks":[{"type":"strong"}]},{"text":"rootfs/","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" destinations.","type":"text","marks":[{"type":"strong"}]},{"text":" Files under ","type":"text"},{"text":"rootfs/","type":"text","marks":[{"type":"code_inline"}]},{"text":" were extracted with ","type":"text"},{"text":"sudo tar xpjf","type":"text","marks":[{"type":"code_inline"}]},{"text":" by ","type":"text"},{"text":"jetson-init-image","type":"text","marks":[{"type":"code_inline"}]},{"text":", so they carry root ownership and special mode bits the flashing toolchain reads back. ","type":"text"},{"text":"sudo cp -p","type":"text","marks":[{"type":"code_inline"}]},{"text":" preserves them. Everything else (","type":"text"},{"text":"bootloader/","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"kernel/","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"kernel/dtb/","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"tools/","type":"text","marks":[{"type":"code_inline"}]},{"text":", etc.) is user-owned and does not need ","type":"text"},{"text":"sudo","type":"text","marks":[{"type":"code_inline"}]},{"text":". This applies to both channels.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Channel-overlap precedence.","type":"text","marks":[{"type":"strong"}]},{"text":" If the same ","type":"text"},{"text":"dst","type":"text","marks":[{"type":"code_inline"}]},{"text":" appears in both overlay and manifest, manifest wins (later in the \"Diff-aware copy into bsp_image\" step's loop). This is the desired semantic — manifest entries are freshly built, overlay entries may be older state. Hand-editing binary files into the overlay is discouraged (Build's job is to rebuild them); the precedence rule makes such mistakes recoverable.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"bsp_image","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" is read-only outside Deploy.","type":"text","marks":[{"type":"strong"}]},{"text":" This skill is the only writer in the normal flow (matches the workflow invariant). Hand-edits to ","type":"text"},{"text":"\u003cbsp_image.root_path>/Linux_for_Tegra/","type":"text","marks":[{"type":"code_inline"}]},{"text":" outside Deploy will be silently overwritten on the next promote run if the same path exists in either channel; conversely they will ","type":"text"},{"text":"not","type":"text","marks":[{"type":"em"}]},{"text":" be reverted if no entry shadows them. Both behaviors are wrong for the diff trail — never hand-edit upstream.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Scope is overlay HEAD only (channel A).","type":"text","marks":[{"type":"strong"}]},{"text":" Named tags / manifests / commit ranges are deferred (see below). To promote a historical state, ","type":"text"},{"text":"git -C $LFT_SRC checkout \u003cref>","type":"text","marks":[{"type":"code_inline"}]},{"text":" first, then re-run. The manifest channel has no ranged scope — it reflects whatever ","type":"text"},{"text":"jetson-build-source","type":"text","marks":[{"type":"code_inline"}]},{"text":"'s last run produced.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"No automatic rollback on partial failure.","type":"text","marks":[{"type":"strong"}]},{"text":" If ","type":"text"},{"text":"cp","type":"text","marks":[{"type":"code_inline"}]},{"text":" fails partway through, ","type":"text"},{"text":"bsp_image","type":"text","marks":[{"type":"code_inline"}]},{"text":" is left in an intermediate state. Fix the underlying cause (usually permissions / disk full) and re-run — the \"Diff-aware copy into bsp_image\" step will resume by skipping already-promoted files.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Kernel ","type":"text","marks":[{"type":"strong"}]},{"text":"Image","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" mirror + initramfs refresh.","type":"text","marks":[{"type":"strong"}]},{"text":" Gated on copy-pass writes to ","type":"text"},{"text":"kernel/Image","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"rootfs/lib/modules/*","type":"text","marks":[{"type":"code_inline"}]},{"text":"; the mirror feeds the refresh's chroot. Both are diff-aware and skipped on pure-overlay edits. ","type":"text"},{"text":"tools/l4t_update_initrd.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":" must exist in ","type":"text"},{"text":"bsp_image","type":"text","marks":[{"type":"code_inline"}]},{"text":" (ships with ","type":"text"},{"text":"apply_binaries.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":"); a missing tool refuses and routes to ","type":"text"},{"text":"/jetson-init-image","type":"text","marks":[{"type":"code_inline"}]},{"text":". See ","type":"text"},{"text":"references/kernel-image-and-initramfs.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/kernel-image-and-initramfs.md","title":null}},{"type":"code_inline"}]},{"text":" for the full contract and failure modes.","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Troubleshooting","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Error","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Cause","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Solution","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Overlay has uncommitted changes at \u003cLFT_SRC>","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Customize-* edits not committed before promote","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Run ","type":"text"},{"text":"git -C $LFT_SRC commit","type":"text","marks":[{"type":"code_inline"}]},{"text":" (or stash), then re-run.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"origin has N unpulled commits on \u003cupstream>","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Remote overlay diverged from local","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"git -C $LFT_SRC pull","type":"text","marks":[{"type":"code_inline"}]},{"text":", resolve conflicts, then re-run.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Both overlay and manifest are empty — nothing to promote","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"No Customize-* commits and no Build manifest","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Run a customize-* skill or ","type":"text"},{"text":"/jetson-build-source","type":"text","marks":[{"type":"code_inline"}]},{"text":" first.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Kernel-side source(s) changed since last /jetson-build-source","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Freshness gate detected unprocessed customize-* edits under ","type":"text"},{"text":"Source/bsp_sources/","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Commit pending edits, run ","type":"text"},{"text":"/jetson-build-source","type":"text","marks":[{"type":"code_inline"}]},{"text":", re-run promote.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Manifest entry references missing build output: \u003csrc>","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"bsp_sources/","type":"text","marks":[{"type":"code_inline"}]},{"text":" build outputs wiped or stale manifest","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Re-run ","type":"text"},{"text":"/jetson-build-source","type":"text","marks":[{"type":"code_inline"}]},{"text":" to regenerate.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Build manifest at \u003cMANIFEST> is not valid YAML","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Manifest hand-edited or partially written","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Re-run ","type":"text"},{"text":"/jetson-build-source","type":"text","marks":[{"type":"code_inline"}]},{"text":" to rewrite the manifest.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"cp: permission denied","type":"text","marks":[{"type":"code_inline"}]},{"text":" under ","type":"text"},{"text":"rootfs/","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Missing ","type":"text"},{"text":"sudo","type":"text","marks":[{"type":"code_inline"}]},{"text":" privilege on the host","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Run on an account that can ","type":"text"},{"text":"sudo cp","type":"text","marks":[{"type":"code_inline"}]},{"text":"; re-run resumes via diff-aware copy.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Profile lacks ","type":"text"},{"text":"bsp_image:","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":"source:","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Workspace not bootstrapped","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Run ","type":"text"},{"text":"/jetson-init-image","type":"text","marks":[{"type":"code_inline"}]},{"text":" and/or ","type":"text"},{"text":"/jetson-init-source","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"tool not found at \u003cLFT_DST>/tools/l4t_update_initrd.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"tools/","type":"text","marks":[{"type":"code_inline"}]},{"text":" was pruned, or bsp_image extracted from a non-NVIDIA tarball","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Re-run ","type":"text"},{"text":"/jetson-init-image","type":"text","marks":[{"type":"code_inline"}]},{"text":" to repopulate.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"l4t_update_initrd.sh exited non-zero","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Insufficient sudo, broken rootfs (missing ","type":"text"},{"text":"lib/modules/\u003cver>/modules.dep","type":"text","marks":[{"type":"code_inline"}]},{"text":"), or out-of-space ","type":"text"},{"text":"/tmp","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Run ","type":"text"},{"text":"depmod -a -b \u003cLFT_DST>/rootfs \u003cver>","type":"text","marks":[{"type":"code_inline"}]},{"text":" against the rootfs first; verify ","type":"text"},{"text":"/tmp","type":"text","marks":[{"type":"code_inline"}]},{"text":" headroom; rerun promote.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"DUT boots with stale kernel / modules after promote, modules fail to load with ","type":"text"},{"text":"disagrees about version of symbol …","type":"text","marks":[{"type":"code_inline"}]},{"text":", or initramfs ships pre-customize modules even after the refresh ran","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"The mirror / refresh gate didn't fire (manual hand-edit under ","type":"text"},{"text":"\u003cLFT_DST>","type":"text","marks":[{"type":"code_inline"}]},{"text":" outside the skill), or ","type":"text"},{"text":"rootfs/boot/Image","type":"text","marks":[{"type":"code_inline"}]},{"text":" drifted from ","type":"text"},{"text":"kernel/Image","type":"text","marks":[{"type":"code_inline"}]},{"text":" so the chrooted refresh built against the stale kernel","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Force the gate by ","type":"text"},{"text":"sudo touch \u003cLFT_DST>/kernel/Image","type":"text","marks":[{"type":"code_inline"}]},{"text":" + re-run promote, or run the two steps manually: ","type":"text"},{"text":"sudo cp -p \u003cLFT_DST>/kernel/Image \u003cLFT_DST>/rootfs/boot/Image && cd \u003cLFT_DST> && sudo ./tools/l4t_update_initrd.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":". Then re-flash. See ","type":"text"},{"text":"references/kernel-image-and-initramfs.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/kernel-image-and-initramfs.md","title":null}},{"type":"code_inline"}]},{"text":".","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Spec status","type":"text"}]},{"type":"paragraph","content":[{"text":"Locked in for v0.2.0:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Two-channel scope","type":"text","marks":[{"type":"strong"}]},{"text":" — overlay HEAD + build manifest, both diff-aware, both copying into ","type":"text"},{"text":"\u003cbsp_image.root_path>/Linux_for_Tegra/","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Channel-overlap precedence","type":"text","marks":[{"type":"strong"}]},{"text":" — manifest wins on ","type":"text"},{"text":"dst","type":"text","marks":[{"type":"code_inline"}]},{"text":" collision.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Source-repo collision check","type":"text","marks":[{"type":"strong"}]},{"text":" — overlay only; manifest has no remote concept and source repos under ","type":"text"},{"text":"bsp_sources/","type":"text","marks":[{"type":"code_inline"}]},{"text":" are not fetched (their state was sealed when ","type":"text"},{"text":"jetson-build-source","type":"text","marks":[{"type":"code_inline"}]},{"text":" wrote the manifest).","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Atomicity","type":"text","marks":[{"type":"strong"}]},{"text":" — fail-fast, no rollback. Diff-aware copy makes resume natural.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Audit trail","type":"text","marks":[{"type":"strong"}]},{"text":" — stdout-only at promote time. The overlay tracker's git log is the canonical record for channel A; the manifest itself is the canonical record for channel B.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Kernel Image mirror + initramfs refresh.","type":"text","marks":[{"type":"strong"}]},{"text":" Locked in as a paired step. The mirror copies ","type":"text"},{"text":"kernel/Image","type":"text","marks":[{"type":"code_inline"}]},{"text":" → ","type":"text"},{"text":"rootfs/boot/Image","type":"text","marks":[{"type":"code_inline"}]},{"text":" whenever the copy pass touched ","type":"text"},{"text":"kernel/Image","type":"text","marks":[{"type":"code_inline"}]},{"text":"; the refresh runs ","type":"text"},{"text":"tools/l4t_update_initrd.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":" whenever ","type":"text"},{"text":"kernel/Image","type":"text","marks":[{"type":"code_inline"}]},{"text":" or any ","type":"text"},{"text":"rootfs/lib/modules/*","type":"text","marks":[{"type":"code_inline"}]},{"text":" was promoted, rebuilding both ","type":"text"},{"text":"bootloader/l4t_initrd.img","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":"rootfs/boot/initrd","type":"text","marks":[{"type":"code_inline"}]},{"text":". Inseparable because the refresh chroots into ","type":"text"},{"text":"rootfs/","type":"text","marks":[{"type":"code_inline"}]},{"text":" and resolves the kernel through ","type":"text"},{"text":"/boot/Image","type":"text","marks":[{"type":"code_inline"}]},{"text":" — the mirror has to run first. Closes both module-shadowing and vermagic-skew failure modes; both diff-aware, both skipped on overlay-only edits. Full contract in ","type":"text"},{"text":"references/kernel-image-and-initramfs.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/kernel-image-and-initramfs.md","title":null}},{"type":"code_inline"}]},{"text":".","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Still deferred:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Named-tag / commit-range scope","type":"text","marks":[{"type":"strong"}]},{"text":" for the overlay channel. Revisit when a \"promote release X\" use case appears.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Manifest history.","type":"text","marks":[{"type":"strong"}]},{"text":" Currently only the last build's manifest exists; if a user wants to roll bsp_image back to a previous build state, they'd need to re-run ","type":"text"},{"text":"/jetson-build-source","type":"text","marks":[{"type":"code_inline"}]},{"text":" at the prior commit. A manifest archive (saved per-build-mode or per-commit) would enable rollback without rebuild.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Sidecar manifest in ","type":"text","marks":[{"type":"strong"}]},{"text":"bsp_image","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":".","type":"text","marks":[{"type":"strong"}]},{"text":" Revisit when promotion happens on a host that does not have access to the overlay tracker repo (or the workspace's manifest file).","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"References","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/kernel-image-and-initramfs.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/kernel-image-and-initramfs.md","title":null}},{"type":"code_inline"}]},{"text":" — full contract for the kernel ","type":"text"},{"text":"Image","type":"text","marks":[{"type":"code_inline"}]},{"text":" mirror + ","type":"text"},{"text":"l4t_update_initrd.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":" refresh: shell snippets, failure modes, tool semantics, output filenames.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"../../context/target-platform-contract.md","type":"text","marks":[{"type":"link","attrs":{"href":"../../context/target-platform-contract.md","title":null}},{"type":"code_inline"}]},{"text":" — target-platform contract.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"../../context/bsp-customization-workflow.md","type":"text","marks":[{"type":"link","attrs":{"href":"../../context/bsp-customization-workflow.md#workflow-invariants","title":null}},{"type":"code_inline"}]},{"text":" — workspace edit protocol (this skill is the promote leg of Deploy).","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"../jetson-init-source/SKILL.md","type":"text","marks":[{"type":"link","attrs":{"href":"../jetson-init-source/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" — Setup; materializes the overlay tracker this skill reads (channel A) and authors ","type":"text"},{"text":"source.toolchain","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"../jetson-build-source/SKILL.md","type":"text","marks":[{"type":"link","attrs":{"href":"../jetson-build-source/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" — Build builder; writes the ","type":"text"},{"text":".build-manifest.yaml","type":"text","marks":[{"type":"code_inline"}]},{"text":" this skill reads (channel B).","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"../jetson-flash-image/SKILL.md","type":"text","marks":[{"type":"link","attrs":{"href":"../jetson-flash-image/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" — next leg; flashes the just-promoted bsp_image to the DUT.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"../jetson-validate-image/SKILL.md","type":"text","marks":[{"type":"link","attrs":{"href":"../jetson-validate-image/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" — final leg; static + on-target validation.","type":"text"}]}]}]}]},"metadata":{"date":"2026-11-02","name":"jetson-promote-image","tags":["bsp","promote","deploy"],"author":"@skillopedia","source":{"stars":3825,"repo_name":"skills","origin_url":"https://github.com/NVIDIA/skills/blob/HEAD/skills/jetson-promote-image/SKILL.md","repo_owner":"NVIDIA","body_sha256":"8cdfa699298ee267d83012085ab56232688edbfdf791abae2b0e05b5df524ee6","cluster_key":"b0e3e165ee217c3b881447371c87cdf00f4a83c42a30399efb8d144b516109fd","clean_bundle":{"format":"clean-skill-bundle-v1","source":"NVIDIA/skills/skills/jetson-promote-image/SKILL.md","text_bytes":28937,"source_commit":"25340619336e89bcc40365c28bfe9e790430468e","skills_sh_rank":12167,"attachment_count":6,"text_attachments":6,"attachment_storage":"skill_attachments","binary_attachments":0},"cluster_size":1,"skill_md_path":"skills/jetson-promote-image/SKILL.md","import_metadata":{"date":"2026-11-02","author":"@skillopedia","version":"0.0.1","category":"devops-infrastructure","category_label":"DevOps"},"exact_dupes_collapsed_into_this":0},"license":"Apache-2.0","version":"0.0.1","category":"devops-infrastructure","metadata":{"tags":["bsp","promote","deploy"],"team":"pts","author":"Jetson Team","domain":"meta","data-classification":"public"},"import_tag":"skills-sh-top20k-2026-11","description":"Use to promote overlay files and built artifacts into the staged BSP image. Do NOT use to flash or build. Triggers: promote bsp image."}},"renderedAt":1793671883501}

Promote BSP Image Purpose Stage every Customize- and Build output into so it is ready for . This is the promote leg of Deploy — it copies files, never flashes and never builds. Prerequisites - Active target-platform profile with both and resolved (run and first). - initialized as a git repo (overlay tracker) with a clean working tree. - extracted from a BSP tarball + already run. - , , , and (for destinations) on the host. - + from (required when kernel-side repos have customize- commits). Overview This is the promote leg of Deploy — see for the pipeline view. The two channels this skill walk…