You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A rulebook body ships verbatim. sync applies no transform to it, so a Markdown link or a {harness_home_dir} token authored in a rulebook body reaches the deployed artifact unconverted and resolves to nothing.
Relative paths are also unreliable for an agent to resolve on its own. Claude Code has standing reports that a relative path in a SKILL.md is not resolved against the skill's directory, because the model cannot know its install directory (#17741, #56325, skills#1153). Absolute paths produced by the delivery pipeline rather than resolved by the model are the reliable form, and that is already what rewriteMarkdownPaths emits for skills and subagents.
No rulebook contains a link today, so this is enabling work rather than corrective. Its value is that it makes the destination-tier doctrine in content/guidance/README.md actionable: a harness-neutral host cannot carry a harness-scoped path, and the prescribed remedy is to move such content into an ambient rulebook, which helps only once a rulebook can carry a path at all. content/guidance/shared/AGENTS.md cites four _data/ files as prose ("in the agents skills tree") for exactly that reason. Those citations stay prose until their content migrates, which this change unblocks and does not itself perform.
Context
In scope: Render rulebook bodies per harness with the two transforms that concern paths, namely Markdown link rewriting (rewriteMarkdownPaths) and template variables (rewriteTemplateVariables, covering {harness_home_dir} and {harness_id}), at both delivery points: the rulebook-skill write loop and ambient region injection.
Out of scope:
{tool:} and {skill:}/{subagent:} invocation tokens. They carry dependency-edge semantics and would require extending edge extraction to rulebooks.
Links from one rulebook to another. An ambient-only target has no file to address, and dependencies: already expresses that relationship.
content/guidance/shared/, which installs both to the harness-neutral ~/.agents/AGENTS.md and, through include expansion, into each harness guidance file. Its neutral copy is why a link authored there cannot resolve.
Design context: the refined plan 20260729-023321Z_ambient-rulebooks-per-harness_plan-v2.md under this project's tickets/1088/ artifact directory (Tasks 2 and 4). That plan covers a larger scope that has since been split; this ticket is the rendering slice only.
Proposed solution
Rulebook bodies pass through a per-harness render before delivery, validated in the same pre-write pass that fails a dry run with nothing written.
Anchoring at the content root. The rewrite passes guidance/rulebooks/<slug>.md as the file path and the target harness's homeDir as the prefix. A source-tree link such as ../../skills/_data/concision.md then normalizes to skills/_data/concision.md and emits the harness's absolute path. No mapping layer is needed, because content/skills/ and content/scripts/ are laid out congruently with their deployed locations.
Allowed roots are skills/ and scripts/, not subagents/. Those two are the roots whose source layout matches their deployed layout under every harness. subagents/ is excluded because a subagent definition is dispatched rather than read as a document, so there is no link worth authoring into one; its deployed directory name also diverges by harness, but the renderer could map that. _partials/, collections/, and guidance/ never deploy as files. Widening later is easier than narrowing, and silently emitting a path nothing creates is the failure this work exists to prevent.
Validation splits by what each mechanism can know. The renderer enforces the root allowlist and content-root containment, both lexical and always correct. Existence and anchor-fragment checking stays in content-link-resolution.test.ts, extended to cover guidance/rulebooks/. The renderer deliberately does not check existence: it would resolve a target against the rulebook's own content root, which would reject a project-source or machine-local rulebook's link to library content, since no single content root models the deployed tree's union of library and source content.
Rulebook resolution moves to src/lib/ beside the renderer, matching where skill and subagent resolution already live.
Acceptance criteria
Must have
A link target under an allowed root emits the target harness's absolute path, with anchor fragments preserved.
A target in a rejected root, or one escaping the content root, fails the run with an error naming the rulebook, the authored target, and the reason.
~-prefixed, absolute, http(s), and anchor-only targets pass through untouched.
{harness_home_dir} and {harness_id} expand per target harness.
A link target beginning with a template token expands to the harness path rather than being mangled into a relative path. Applies to skills and subagents as well as rulebooks.
A rulebook delivered to two harnesses yields the correct absolute path in each, in both skill delivery and ambient delivery.
Validation runs in the same pre-write pass as assertDeclaredSkillsRender, so a bad link fails a dry run with nothing written.
content-link-resolution.test.ts covers guidance/rulebooks/, and its claim that guidance/ is copied verbatim with no link rewriting is corrected.
codeassembly-content-specification.md documents the link convention, the allowed roots, and what a rejected target reports. Its claim that rulebook bodies bypass the render pass is made precise rather than deleted: rulebooks receive link and template rewriting but not invocation tokens, which is why dependencies: remains their edge mechanism.
Problem
A rulebook body ships verbatim.
syncapplies no transform to it, so a Markdown link or a{harness_home_dir}token authored in a rulebook body reaches the deployed artifact unconverted and resolves to nothing.Relative paths are also unreliable for an agent to resolve on its own. Claude Code has standing reports that a relative path in a
SKILL.mdis not resolved against the skill's directory, because the model cannot know its install directory (#17741, #56325, skills#1153). Absolute paths produced by the delivery pipeline rather than resolved by the model are the reliable form, and that is already whatrewriteMarkdownPathsemits for skills and subagents.No rulebook contains a link today, so this is enabling work rather than corrective. Its value is that it makes the destination-tier doctrine in
content/guidance/README.mdactionable: a harness-neutral host cannot carry a harness-scoped path, and the prescribed remedy is to move such content into an ambient rulebook, which helps only once a rulebook can carry a path at all.content/guidance/shared/AGENTS.mdcites four_data/files as prose ("in the agents skills tree") for exactly that reason. Those citations stay prose until their content migrates, which this change unblocks and does not itself perform.Context
In scope: Render rulebook bodies per harness with the two transforms that concern paths, namely Markdown link rewriting (
rewriteMarkdownPaths) and template variables (rewriteTemplateVariables, covering{harness_home_dir}and{harness_id}), at both delivery points: the rulebook-skill write loop and ambient region injection.Out of scope:
{tool:}and{skill:}/{subagent:}invocation tokens. They carry dependency-edge semantics and would require extending edge extraction to rulebooks.ambient-only target has no file to address, anddependencies:already expresses that relationship.content/guidance/shared/, which installs both to the harness-neutral~/.agents/AGENTS.mdand, through include expansion, into each harness guidance file. Its neutral copy is why a link authored there cannot resolve.Design context: the refined plan
20260729-023321Z_ambient-rulebooks-per-harness_plan-v2.mdunder this project'stickets/1088/artifact directory (Tasks 2 and 4). That plan covers a larger scope that has since been split; this ticket is the rendering slice only.Proposed solution
Rulebook bodies pass through a per-harness render before delivery, validated in the same pre-write pass that fails a dry run with nothing written.
Anchoring at the content root. The rewrite passes
guidance/rulebooks/<slug>.mdas the file path and the target harness'shomeDiras the prefix. A source-tree link such as../../skills/_data/concision.mdthen normalizes toskills/_data/concision.mdand emits the harness's absolute path. No mapping layer is needed, becausecontent/skills/andcontent/scripts/are laid out congruently with their deployed locations.Allowed roots are
skills/andscripts/, notsubagents/. Those two are the roots whose source layout matches their deployed layout under every harness.subagents/is excluded because a subagent definition is dispatched rather than read as a document, so there is no link worth authoring into one; its deployed directory name also diverges by harness, but the renderer could map that._partials/,collections/, andguidance/never deploy as files. Widening later is easier than narrowing, and silently emitting a path nothing creates is the failure this work exists to prevent.Validation splits by what each mechanism can know. The renderer enforces the root allowlist and content-root containment, both lexical and always correct. Existence and anchor-fragment checking stays in
content-link-resolution.test.ts, extended to coverguidance/rulebooks/. The renderer deliberately does not check existence: it would resolve a target against the rulebook's own content root, which would reject a project-source or machine-local rulebook's link to library content, since no single content root models the deployed tree's union of library and source content.Rulebook resolution moves to
src/lib/beside the renderer, matching where skill and subagent resolution already live.Acceptance criteria
Must have
~-prefixed, absolute,http(s), and anchor-only targets pass through untouched.{harness_home_dir}and{harness_id}expand per target harness.assertDeclaredSkillsRender, so a bad link fails a dry run with nothing written.content-link-resolution.test.tscoversguidance/rulebooks/, and its claim thatguidance/is copied verbatim with no link rewriting is corrected.codeassembly-content-specification.mddocuments the link convention, the allowed roots, and what a rejected target reports. Its claim that rulebook bodies bypass the render pass is made precise rather than deleted: rulebooks receive link and template rewriting but not invocation tokens, which is whydependencies:remains their edge mechanism.