pub(super) fn splice_project_instructions_component(
export: &mut BundleExport,
files: &[ProjectInstructionFile],
) -> Result<(), String>Expand description
Splice native-memory files into an already-built bundle export’s
bundle.json manifest and files list, adding components.memory (ABF
v0.2 §2.3). Kept OUTSIDE bundle_export.rs deliberately — that
module’s export_bundle() is scoped to a bundle’s own components
(instructions/skills/MCP/accounts) with no concept of “agent” or
native memory at all; memory is agent-scoped, not bundle-scoped, so
splicing it in here (the RPC-handler layer, which already resolves
other agent-scoped data like skill rows) keeps that module’s
documented scope intact rather than growing it a fifth, unrelated
component category. A no-op when memory_files is empty — matches the
existing omit-empty-components convention used elsewhere in the
manifest.
Carry the agent’s project instructions into the export as
components.projectInstructions.
Phase 3 of SPEC_INSTRUCTION_AND_MEMORY_PORTABILITY_2026_09_09.md. Files
land under instructions/project/<sanitized-path>, and each manifest entry
carries its original path, a contentHash, and an owner.
owner is the load-bearing field. It is what stops this from becoming a
way to install one repository’s instructions into another: an importer that
treated a foreign entry as content to write would be doing precisely what
SPEC_CLAUDE_MD_OWNERSHIP_PROTECTION_2026_08_22.md exists to prevent.
Import surfaces these and never applies them (spec §5.2), so an operator who
wants them acts deliberately.
Only files that exist and were readable are carried — there is nothing to
put in an archive otherwise. Their absence from the manifest is therefore
not a claim that the source agent had none; agent.project_instructions is
where the fuller picture, including absent and unreadable files, lives.
“Readable” is decided by error/truncated, NOT by whether the content is
empty (Codex P2, PR #3163). A real, readable, zero-byte CLAUDE.md is a
fact about the source agent — dropping it would make the export
indistinguishable from one where the file was absent, which is the exact
kind of quiet lie this component exists to remove.
Paths go through the same sanitizer the exporter uses for context files, so a scanned path can never write outside the archive’s own tree.