ADR 0167: render reproducible artifact delivery cards
Date: 2026-09-04 Status: Accepted
Context
Section titled “Context”An artifact workspace often contains a primary result, visual review files, machine-readable reports, and directories with intermediate output. Agents handed these files to an operator by composing links and copyable paths in chat. That manual step produced inconsistent labels, omitted the workspace path, and could not be reproduced after context compaction or a handoff to another agent.
Most artifacts already have a useful root structure, so requiring a second manifest before the command can render anything would make the default path needlessly manual. The artifact lifecycle manifest owns purpose, retention, and holds. Adding presentation-specific destinations to that schema would couple a stable cleanup contract to a user-interface concern and would force a lifecycle schema migration whenever the card format changed.
Alternatives considered
Section titled “Alternatives considered”- Keep a prose template in agent instructions. A template describes the desired shape but still leaves every agent to locate, validate, order, and format the destinations.
- Recursively scan every file. A workspace can contain many intermediates, and a deep walk can produce an unbounded card. Root-level entries provide useful navigation without flattening the workspace.
- Store the destinations in the artifact lifecycle manifest. This would make cleanup and delivery evolve under one schema even though neither depends on the other.
- Build the formatter only in one embedding host. Other Harnery users and adapters would continue to produce different handoffs for the same managed artifact.
Decision
Section titled “Decision”Harnery adds artifacts delivery-card <ref>. With no delivery manifest, the
command renders immediately from the managed artifact. It includes the artifact
folder and discovers up to five visible root-level directories and regular
files. Directories come first, followed by files, and each group is sorted by
name. Harnery omits its own metadata, hidden entries, symlinks, and special
files. The card reports the omitted count so the output stays compact.
A call with repeatable --url and --path options validates and saves selected
destinations, then prints the card. A non-empty saved manifest is an allowlist,
so the renderer does not append unrelated root entries. A later call without
item options reproduces the saved selections. --title sets the heading; when
supplied alone, it updates the heading while preserving the saved items. A
missing manifest defaults to the title Artifact delivery and an empty
selected-item list.
The delivery data lives in .harnery-delivery.json at the root of the managed
workspace. It has its own versioned schema and contains a title plus ordered URL
and artifact-relative path items. The artifact folder does not need a manifest
entry because the renderer includes it automatically.
Local paths must exist inside the managed workspace. Validation resolves real
paths and refuses absolute inputs, lexical traversal, and symlink escapes. Web
destinations accept only HTTP and HTTPS. Labels are case-insensitively unique,
and Artifact folder is reserved for the automatic row.
The command writes Markdown to standard output so an agent can paste it without reformatting. The first section links each destination through its short label. The second is a fenced plain-text block with the complete URLs and paths for copying.
Artifact files and folders open through the configured Harnery dashboard. The
renderer looks for the newest live tunnel whose upstream matches the dashboard
port. It uses that tunnel as the link origin when available and falls back to
the local dashboard origin when no matching tunnel is live. Both the local gate
and the provider process must be running. Explicit --url destinations remain
unchanged because the caller owns them.
WSL output uses a UNC display path in the plain-text block; other platforms use native absolute paths. Link destinations remain browser URLs on every platform.
Result
Section titled “Result”Without a delivery manifest, the command returns a card with at most five root entries. An optional manifest narrows the card to the files and URLs the operator needs. Any later agent can regenerate the handoff without reconstructing it from chat history, and broken or unsafe local destinations fail before the card is saved. Live tunnels make the same generated card usable from another device, while local sessions keep working without a tunnel. The delivery schema can evolve separately from the lifecycle schema.
The card does not extend retention or make a result durable. Existing artifact holds, release, and cleanup rules remain the authority for workspace lifetime.
Scope and promotion
Section titled “Scope and promotion”This decision governs operator-facing links to files already stored in a managed Harnery artifact. It does not choose which files a production workflow must generate, upload remote media, or replace a project’s durable publication and storage rules.