Artifact Links¶
Artifact links are typed relationships between SASE artifacts. They answer "why are these durable records connected?" without overloading prompt citations, bead dependencies, or free-text notes.
An artifact is any durable record addressable by an artifact reference: a plan,
research report, bead, completed agent, Patch, stitch, or indexed file. Each artifact
has a canonical <kind>:<argument> identity. An artifact markdown file is the
Markdown document or generated page where SASE renders that artifact's typed links.
Relation Registry¶
The registry is closed. Use one of these slugs exactly:
| Relation | Inverse | Directed | Written by |
|---|---|---|---|
cites |
cited-by |
yes | prompt references and structured header derivation |
read |
read-by |
yes | sase artifact read |
related |
related |
no | CLI / plan inlet; RELATED: migration |
supersedes |
superseded-by |
yes | CLI / plan inlet |
implements |
implemented-by |
yes | CLI / plan inlet; plan, agent, and stitch projections |
derives-from |
derived-into |
yes | CLI / plan inlet; research lineage derivation |
produced-by |
produced |
yes | projected from a stitch's recorded agent or an epic's creating agent |
launched |
launched-by |
yes | projected from a configured job and its published agents |
awaits |
awaited-by |
yes | projected from a published agent's wait_for_beads |
blocks and depends-on are reserved. Use sase bead dep for scheduling and blocking
relationships instead of storing those as artifact links.
Run sase artifact link relation list to inspect the closed registry, or
sase artifact link relation show <slug> for one relation's direction, positive and
negative examples, and recommended endpoint kinds. Both forms accept -j/--json.
Direction matters: the replacement supersedes the old artifact, a plan or agent
implements a bead, a stitch is produced-by an agent, a job launched an
agent, a waiting agent awaits a bead, and a derived report derives-from its
source. related is undirected. Only related, supersedes, implements, and
derives-from are writable by the CLI; cites and read are observational rows, while
produced-by, launched, and awaits are read-only projections from other durable
evidence.
Commands¶
Create or update a deliberate link:
sase artifact link add <source-ref> <relation> <target-ref> "<why>"
The source is always explicit; it never defaults to the current agent. References may
include their prompt-only leading @. <why> must be one non-empty line of at most 240
characters. Repeating an identical edge is an unchanged success rather than a second
row.
List one artifact's neighborhood, or the current project's recent links:
sase artifact link list <ref> -d both
sase artifact link list -l 20 -R related
Without a reference, list shows the current project's newest 50 rows. With one, it
shows that artifact's neighborhood. -d in|out|both, -R/--relation, and -o/--origin
(manual, migrated, prompt_ref, read, derived, or projected) narrow it;
-l 0 is unlimited and -j emits a stable JSON array. The default --source index
reads the rebuildable machine-local aggregate and includes computed projections.
--source store recomputes rows from durable document and bead truth plus pending event
outbox entries, and excludes computed projections. Before the legacy cutover is
complete, that durable truth also includes the frozen document-sidecar links/ indexes;
after cutover it comes from immutable events and bead records.
Ask SASE for write-free, hard-evidence suggestions before adding a deliberate edge:
sase artifact link suggest
sase artifact link suggest plan:202608/example.md -l 20
Suggestions come only from deterministic filename lineage, a shared bead or epic,
overlapping audited-read sets, or an audited read-log candidate. Existing persisted
links are excluded (related is compared in either direction). Each row names its
signal and evidence. This command never writes graph rows, companion files, or commits;
review a suggestion and use link add yourself when it expresses the intended meaning.
Remove links between a pair:
sase artifact link rm <source-ref> <target-ref>
sase artifact link rm <source-ref> <target-ref> -R implements
Read an artifact as context with an audited reason:
sase artifact read <ref> "<why you need this context>"
read strips leading frontmatter plus managed Links and Referenced By blocks before
printing Markdown. Inside a SASE agent run with an agent identity, it also records a
read edge from the agent to the artifact. Outside an agent run it still prints the
artifact and writes the audit row, but warns that no graph edge was recorded. show,
path, and open remain silent reads.
After the body, read prints a Links: footer to stderr with up to five one-hop
neighbors, semantic links first, followed by (+N more) when needed. Reading an
artifact that is the target of supersedes also emits a direct warning naming its
replacement.
link add, link rm, and migrate-notes --apply publish immutable operations. A
removal is a tombstone over the active operation IDs the command observed; it does not
delete history. The shared Rust reducer folds those operations into the current graph
rows that link list displays.
Projected relationships¶
Some relationships are computed into the machine-local read model instead of being stored as link sidecars:
- a published agent's
bead_id,epic_bead_id, orphase_bead_idprojectsagent:<name> implements bead:<id>; - a primary-repository commit with a
SASE_BEADtrailer projectsstitch:<sha> implements bead:<id>; - a commit with a
SASE_AGENTtrailer (or legacyAGENT) projectsstitch:<sha> produced-by agent:<name>; and - a published agent's
created_epic_ids(recorded bysase bead work) projectsbead:<epic> produced-by agent:<name>, and an epic-tier plan bead whosecreated_bynames an agent projects the same edge, so unpublished planners get the edge too; and - a published job-agent name that resolves against the live AXE configuration projects
job:<routine>/<job> launched agent:<name>; and - a published agent's
wait_for_beads(from%wait(bead=<id>)) projectsagent:<name> awaits bead:<id>.
Projected rows carry origin: projected and a created_by: projection:<rule> marker.
They appear in sase artifact link list, sase artifact doctor, and sase's TUI
alongside durable links, but they are recomputed read-model data: link rm and sase's
TUI remove action cannot delete them. Change the durable source evidence instead, then
refresh or repair the aggregate. The health check compares the aggregate against both
durable sidecar truth and these expected projections.
Rendering¶
SASE renders deliberate manual and migrated links near the top of the artifact markdown
file in a managed ## Links table. Automatic prompt citations and audited reads render
at the bottom in ## Referenced By.
When a prompt expands a document artifact reference, SASE may append up to five one-hop,
directed semantic neighbors as (linked: …). Only implements, derives-from, and
supersedes participate; the expansion is never transitive, and it omits the broad
related relation plus observational cites / read rows.
Markdown document artifacts are their own artifact markdown file. Non-Markdown files use
a sibling <stem>.md companion created lazily on the first link. Beads, agents, and
Patches use generated pages, so agents should update their underlying stores with SASE
commands and never hand-edit those generated pages. Stitches have no page of their own;
links to a stitch render on the other artifact.
Browsing links in sase's TUI¶
When the selected Agent, Artifact, or AXE job has links, sase's TUI shows a contextual
link rail. Press $ to arm it, then $ again for the first link, 1-9 for a
numbered link, or 0 for the complete links panel. A projected group may occupy one
rail entry; choosing it opens a panel scoped to that group instead of guessing which
member to follow.
The panel explains relation direction, provenance, rationale, and missing targets, and
warns when the aggregate is stale. a-z follow the first 26 rows directly, Enter
follows the highlighted row, and arrows or Ctrl+N/Ctrl+P move the highlight. -
removes a writable durable link; projected rows are read-only. Cross-tab follows record
a 32-hop trail: Ctrl+O walks backward and Ctrl+Shift+O walks forward, restoring the
prior tab, pane, project scope, query, selection, and supported fold state. Ordinary
navigation starts a new trail.
Authoring links in a proposed plan¶
An agent may attach deliberate links while authoring a plan by adding a transient
links: list to its YAML frontmatter:
---
tier: tale
title: Implement the artifact browser
goal: Make historical artifacts searchable
size: small
links:
- ref: bead:sase-123
relation: implements
description: This plan implements the accepted task
---
Each entry requires string ref, relation, and description values.
sase plan propose validates the entire list before mutating the proposal, restricts it
to the four CLI-writable relations, and enforces the registry's recommended direction
and endpoint kinds. It then removes links: from the archived plan, persists the rows
with manual origin, and refreshes the managed ## Links block. The list is an
authoring inlet, not retained plan metadata.
Automatic derivation and repair¶
SASE durably derives only relationships backed by deterministic structured evidence:
plan:<path> implements bead:<id>from a plan'sbead_id:frontmatter, when the bead is known to the readable store.agent:<name> cites plan:<path>by following a plan's canonicalPROMPTheader to the archived prompt's canonicalAGENTSentries, after the agent page is published.- A research lead
derives-fromits on-disk__aand__bresearch-swarm siblings.
Derivation runs on relevant plan/archive and sidecar-commit paths. The built-in hourly
AXE artifact_link_backfill job covers older documents in bounded, checkpointed
batches, drains queued read rows for agents that have since published, recomputes
projected relationships, reconciles the machine-local aggregate, and repairs dangling
references from Git rename history. See
Default routines.
Beads¶
Use artifact links for relationship context between beads:
sase artifact link add bead:<new-task-id> related bead:<other-bead-id> "<why>"
Use bead dependencies only for scheduling:
sase bead dep add <blocked-bead-id> <blocking-bead-id>
Historical RELATED: notes remain in bead history. sase artifact link migrate-notes
dry-runs the conversion, and --apply writes typed related edges plus MIGRATED:
notes without deleting the original text.
Legacy index cutover¶
Existing installations may still have mutable per-artifact indexes under document
sidecar links/ trees. Upgrade every SASE machine that can write those sidecars, then
preview the one-time import:
sase artifact link import-indexes
The preview requires clean Git document sidecars, freezes each current HEAD and
links/ tree digest, and reports the unique and duplicate rows, legacy or invalid
queued outbox entries, deterministic baseline-event path, enrolled machine names, and a
capability attestation. Review that fleet list before applying: the marker fences
current binaries only, and older binaries do not understand it.
Apply with the exact token printed by the preview:
sase artifact link import-indexes --apply <attestation>
Apply first commits a link-events/STORE.json fence to every document sidecar, converts
legacy outbox rows, publishes the same deterministic baseline event to every sidecar,
marks the import complete, and rebuilds the aggregate. The operation is idempotent and
resumable: rerunning preview and apply with the reported token completes an interrupted
import rather than creating a second baseline. Once every marker says imported,
current readers ignore the frozen links/ indexes. Do not edit or delete that legacy
tree by hand; sase doctor reports post-import stragglers.
Health and recovery¶
sase artifact doctor reports link health alongside the file index: dangling or
unpublished agent references, stale rendered tables, missing or orphaned companions,
aggregate drift from the expected durable-plus-projected rows, audited reads versus
durable read rows, immutable-event validation or reduction failures, orphaned
tombstones, pending-event age, publication retries, cutover state, queued and dropped
outbox rows, derived-link coverage, and counts by origin and relation. When drift
exists, the report breaks out missing and extra rows by relation, origin, and endpoint.
It exits 1 for unhealthy state; unpublished agent references are informational because a
queued publication may still resolve them.
An orphaned tombstone can arrive before the event version it removes. The reducer keeps that tombstone, suppresses a matching stale legacy row, and continues serving unrelated durable links; the warning converges away when the predecessor event arrives. The current top-level doctor report still counts an orphaned tombstone as unhealthy and exits 1 while it is present.
sase artifact doctor --fix rebuilds the aggregate and managed projections from durable
truth, repairs references whose files can be followed through Git rename history, and
performs the ordinary artifact-index enrichment pass. It does not infer graph state by
parsing hand-authored Markdown, run the legacy-index import, or fabricate missing
events.
The project-level sase doctor -C project.artifact_link_cutover check reports
incomplete or inconsistent cutover markers and any post-import links/ tree changes.
Resume an incomplete import with the attested import-indexes --apply command printed
by the diagnostic.
sase doctor -C project.primary_sidecar_link_dirt flags uncommitted links/ dirt in
sidecar clones nested under a project's primary (human) checkout. That dirt blocks
pull-based sidecar auto-sync. sase doctor -R / --fix-primary-sidecar-links restores
stranded canonical link-index deletions rather than committing them: durable deletions
must land via the machine write lane (hidden host-owned sidecar clones) and reach the
primary through auto-sync.
Storage lifecycle¶
Artifact-link truth lives in several places with different durability:
| Path | Role | Versioned? |
|---|---|---|
Sidecar link-events/v1/<shard>/<digest>.json |
Content-addressed immutable operation objects; the reducer derives the current graph from their union. | Yes. Each owning document sidecar commits the exact event bytes. |
Sidecar link-events/STORE.json |
Fleet-safety fence and legacy-import progress marker (fenced or imported). |
Yes. One canonical marker in every document sidecar. |
Sidecar links/**/*.json |
Frozen legacy schema-v2 indexes, read only before cutover and ignored after every marker is imported. | Historical compatibility data only; never a current write target. |
~/.sase/projects/<key>/link-events/v1/... |
Immutable local receipt history for an event with no document owner, including bead-only events. | No. Machine-local SASE state. |
~/.sase/projects/<key>/artifact-links.json |
Rebuildable aggregate of reduced store rows plus projected relationships, with its lock. | No. Machine-local SASE state. |
~/.sase/projects/<key>/artifact-link-outbox.jsonl |
Replay queue of canonical event payloads awaiting all required durability receipts. | No. Machine-local; retried by publication and hourly housekeeping. |
~/.sase/projects/<key>/artifact-link-outbox-dropped.jsonl |
Audit trail for stale terminal-agent observations that could not become publishable. | No. Machine-local. |
sase artifact link add publishes an edge-put; rm publishes an edge-remove
tombstone. One canonical event is installed in every document sidecar that owns either
endpoint, and one command creates at most one
chore(artifact-links): persist link events commit per affected repository. Bead
ownership is acknowledged through the bead event store. Events with neither a document
nor bead owner use the machine-local event root as their durability receipt; bead-only
events are installed there as immutable history before their bead receipt is accepted.
SASE updates the aggregate only after the operation has every required durability
receipt, so an ephemeral checkout cannot report success while holding the only copy. An
unchanged put or a removal with no active edge writes no new event, but still verifies
that every document-owner sidecar is durably published. The no-op retry therefore fails
when a required owner root is unresolved or its event commits have not reached the
configured remote.
An audited agent read updates the local reduced view and appends a replayable event to
the outbox until the agent's published identity can satisfy document ownership. The
commit workflow and hourly backfill retry those events. Rows for terminal agents that
remain unpublished for 90 days leave the live queue and enter the dropped audit.
Publication commits isolate only canonical event and marker paths, leaving unrelated or
pre-existing sidecar dirt for the normal declaration workflow.