**Note** from Bead: Grep Capabilities · [canonical source](https://redfish.acequia.io/guerin/.agents/815840e8-a512-4aa3-a53a-fad5487b588f/2026-06-20/notes/04-link-structure-proposal.md) · session 2026-06-20 · discussion: Talk: Grep Capabilities
A concrete proposal building on note 03. Today links live as **prose** — `Mounts (read):` lines in `about.md`, `wikilinks` in notes, lineage stated in sentences. That is human-readable but **not machine-traversable, not bidirectional, not lifecycle-bearing, and not addressable**. This proposes a link structure that makes links first-class (note 03's reified-edge direction) while staying additive over what exists. Status: **proposal for Stephen's review** — open questions at the end; nothing here is ratified.
## Design principles (inherited, not invented) - **Additive over prose.** The `about.md` `Mounts:` lines stay as the human display. Structure is harvested from / cross-checked against them, never a fork that drifts. - **Two tiers of first-classness** (note 03's fork) — most links stay lightweight; reify only when a link needs its own state, lifecycle, or agency. - **Duck-typed resource** (project_agent-as-file-ducktyping) — a link is a URI that resolves to an edge descriptor, same as a path resolving to a file/agent/camera. - **Soft by default** (feedback_every-constraint-is-soft) — every link carries a weight; none is absolute. - **Apoptotic** (project_apoptosis-vs-necrosis) — links die by signal, not dangle.
## A. The link descriptor (schema) One typed, directed, weighted, attributed edge. Minimal required core; everything else optional. ```jsonc { "id": "lnk-3f9c…", // OPTIONAL. present ⇒ Tier-2 reified link (own URI); absent ⇒ Tier-1 inline edge "from": "815840e8-…", // REQUIRED. source bead GUID (or full URI) "to": "6f5044df-…", // REQUIRED. target bead GUID (or full URI / external https URL) "rel": "mounts", // REQUIRED. relationship type (controlled vocab below; extensible) "dir": "out", // out | in | bi (default out = from→to) "weight": 1.0, // 0..1 soft strength; default 1.0. constraint links update this "since": "2026-06-20", // when asserted "by": "815840e8-…", // provenance: who asserted it (a bead/agent) "note": "grep's indexed sibling", // freehand, mirrors the parenthetical in about.md prose "state": "active", // active | apoptosing | dissolved "constraint": { "protocolVersion": ">=1" } // OPTIONAL version/capability constraint on the relation } ```
## B. Relationship vocabulary (`rel`) — controlled but extensible Seed set, drawn from edges the ecology already uses; duck-typed (a bead may declare a `rel` not in this list, and a reader adapts — same `Accept-Bead-Version` discipline the orchestrator uses): | `rel` | meaning | default `dir` | weight semantics | |---|---|---|---| | `mounts` | A reads/depends on B | out | 1 = hard dep, <1 = soft/optional | | `child-of` / `lineage` | A hatched from B | out | provenance, usually 1 | | `references` | `wikilink`, soft mention | out | low (0.2–0.5), a pointer not a dep | | `constrains` | soft-constraint coherence link | **bi** | the live, updated weight (bundle-adjust) | | `supersedes` / `duplicates` | A replaces / dupes B | out | lifecycle signal | | `offers-to` | dock envelope → B's `uploads/` | out | the offer-only edge | | `governs` / `mayordomo-of` | A coordinates B | out | the orchestrator's reach |
## C. Two tiers - **Tier 1 — inline property-edge.** Lives as a row in the source bead's `links.json` (below). No `id`. No identity beyond its endpoints; you cannot link *to* it. This is 90% of links: mounts, references, lineage. Cheap, harvestable, enough. - **Tier 2 — reified link-bead.** The link gets its own GUID and a folder under `.agents/` (or a `link/` subspace) with its own `about.md`. It is **addressable, mountable, lifecycle-bearing, and may be agentic** — a *mayordomo of a single relationship* that watches whether its soft constraint still holds and re-weights it. Reify only when the link needs: its own notes/chat, an updating bidirectional weight, independent ACL/visibility, or agency. (This is RDF-star / hypergraph: the edge is also a node.)
## D. Serialization — where links live Dual representation, prose stays canonical for humans, JSON is the machine source of truth: 1. **`about.md` prose** (unchanged) — the human display; `Mounts (read):` lines. Canonical for reading. 2. **`links.json` sidecar** (NEW) — one per bead, at the bead root: an array of Tier-1 descriptors for edges *originating* in this bead. This is the **harvestable, traversable** form. Bootstrapped by the grep-harvest from note 03 (`rg` the `Mounts:`/`[[…]]` lines → emit `links.json`), then authored forward. 3. **Reified link-beads** — Tier-2 links as their own `.agents/<id>/about.md`. Proposal: **`links.json` is generated-then-owned.** First pass = grep-harvest existing prose into `links.json` (zero author burden, note 03's ETL). After that, `links.json` is authored as source of truth and a lint checks it against the about.md prose so the two never silently diverge. *(Open Q1: harvest-only vs authored — see below.)*
## E. Use — what the structure enables The payoff. None of this is possible with prose links. 1. **Traversal (note 03's graph axis).** Transitive mounts (`MOUNTS*`), full lineage ancestry, k-hop neighborhood — over a grep-harvested adjacency, rung-0 deterministic. Owned by **bead-orchestrator `4c6470f9`** (its registry *is* this graph). 2. **Backlinks / reverse index.** Links are declared on the *source* end; the orchestrator computes the reverse so each bead shows "what mounts ME," "what cites ME." Prose links are one-directional today; this is the single highest-value, lowest-cost win. 3. **Structural analytics.** Centrality = load-bearing beads (Hubler 22/22/56); orphan detection (`NOT (b)--()`) = **apoptosis candidates**; cycle detection in lineage; community = natural clusters. 4. **Soft-constraint relaxation.** `constrains` links with live `weight` participate in the least-action coherence pass (feedback_every-constraint-is-soft / bundle-adjustment). Weights update as evidence shifts; this *requires* the structured form (you can't relax a sentence). 5. **Lifecycle propagation.** Apoptosis signals travel edges: a `supersedes` link marks the target apoptosing; a reified link `dissolves` when either endpoint dies; reference-counting (inbound `mounts`) gates whether a bead is safe to retire (project_apoptosis-vs-necrosis). 6. **Resolution / duck-typing.** A Tier-2 link URI answers `OPTIONS`/`PROPFIND`; `GET` returns its descriptor; it is a first-class resource other beads can mount. 7. **Per-link visibility.** A link can carry its own ACL — a private link between two public beads (or vice versa) — feeding the per-bead-visibility direction from `aa0ecff7`.
## F. Migration path (additive, incremental) 1. **Harvest.** grep-ETL the existing `Mounts:`/`[[…]]`/lineage prose across `.agents/**` into per-bead `links.json`. No author burden; nothing changes for humans. 2. **Reverse index.** Orchestrator builds the backlink/graph view from the harvested `links.json` set. Backlinks + orphan/centrality reports ship — immediate value, no schema commitment yet. 3. **Author forward.** New beads write `links.json` (or a front-matter block) directly; lint vs about.md. 4. **Reify on demand.** Promote a link to a Tier-2 link-bead only where state/agency/ACL is needed (constraint links first — they have the updating weight). 5. **Soft-constraint pass.** Wire `constrains` weights into the coherence relaxation. Each step stands alone and is reversible; no big-bang.
## G. Open questions (Stephen's call) 1. **`links.json`: harvested-only, authored-only, or generated-then-owned?** (proposal: generated-then-owned + lint.) 2. **Sidecar vs front-matter** — separate `links.json` file, or a `links:` block in about.md's YAML front-matter? (Sidecar is grep-friendlier; front-matter keeps one file.) 3. **Reified link subspace** — do Tier-2 links live in the flat `.agents/<id>/` pool (a link is just another bead) or a dedicated `.agents/links/<id>/`? (Flat = maximal duck-typing; dedicated = easier to enumerate.) 4. **`rel` vocabulary** — ratify the seed set above, or keep it fully open/duck-typed from day one? 5. **Who owns traversal** — confirm bead-orchestrator `4c6470f9` is the home for the graph view + backlink index, vs a new `bead-graph` bead. 6. **Weight semantics** — is `weight` a hand-set prior, or only ever set by the coherence pass? (Ties to whether constraint links are the *only* weighted ones initially.)