* docs(cargo-context): document graph linking rules and server-side frontmatter enforcement Linking guidelines (how context-graph edges actually form): - Add "Source references and graph edges" sections to cargo-context SKILL.md and references/conventions.md covering the three edge-creating forms (frontmatter references:, markdown links, wikilinks), the no-bare-paths rule, root-relative resolution, optional extensions, broken-target behavior, _template.* exclusion, and YAML/title/summary parsing. - Update cross-reference and template bullets to note edges only form via the three link forms. - Add a source-citation example to references/examples/authoring.md and point the repetition-threshold guidance at frontmatter references:. Frontmatter enforcement (422 / invalidContent): - Update the File conventions frontmatter bullet plus the write and edit sections in SKILL.md to describe server-side rejection and recovery. - Add invalidContent troubleshooting entries (missing fields, malformed YAML, edit-strips-meta) and write/edit error reasons in references/response-shapes.md. - Refresh the cargo-context recap in the top-level overview. * fix(cargo-context): correct frontmatter rules to match backend (soft-fail, no 422) The earlier frontmatter-enforcement docs described a write/edit validation gate (HTTP 422, reason "invalidContent") and a description->graph-summary fallback that the backend does not implement. The runtime write/edit services have no frontmatter validation, and the graph builder fails soft: a missing title falls back to the filename and the node summary to the first paragraph (the graph reads `summary`, never `description`). Align the skill with the actual capability behavior: - Reframe frontmatter as a strong convention, not enforced — missing/empty/ malformed frontmatter is still committed, it just indexes poorly. - Replace the invalidContent/422 notes in SKILL.md (write + edit), the File conventions bullet, conventions.md, authoring.md, and the overview recap. - List the real write/edit failure reasons in response-shapes.md and troubleshooting.md (repositoryNotFound, syncConflict/syncFailed, failedToWrite/failedToEdit, stringNotFound/stringNotUnique, fileNotFound, noOp, deniedPath). - Fix the node-summary source: `summary` (fallback first paragraph), not `description`. The linking rules (edge origins, resolution order, _template/.git exclusion) were already accurate and are unchanged. * fix(cargo-context): stop skills-lint flagging illustrative source-link examples The internal-link checker regex-scans whole files (code fences and inline code included) and resolves every `[text](target)` against the skills repo. The example source paths (`outputs/sales-notes/...`) point into a workspace context repo, so they never exist here and were reported as broken links. Keep the examples but avoid literal `](fake-path)` for the markdown-link form: describe the `[label]`+`(path)` syntax with the path in inline code, and switch the authoring example's body citation to an aliased wikilink (which forms a real edge and isn't matched by the link checker). The frontmatter `references:` and wikilink illustrations are unchanged. skills-lint now passes: 0 errors, 0 warnings. * docs(cargo-context): trim verbose error-reason lists from response-shapes The write/edit "Error reasons" lines enumerated internal failure codes (repositoryNotFound, syncConflict, syncFailed, failedToWrite, etc.) that are accurate but generic infra detail — redundant with the generic error shape documented at the top of the file, and not actionable for context authoring. Keep only the load-bearing points (frontmatter is not validated; the .files/ denied-write case) and point to troubleshooting.md, which already holds the full reason enumeration. --------- Co-authored-by: Claude <noreply@anthropic.com>
9.0 KiB
Context repo conventions
The conventions below are inherited from the canonical context repository getcargohq/cargo-workspaces. When in doubt, read its README.md and the _template.md file in the relevant domain.
Domains
| Domain | Purpose |
|---|---|
global/ |
Company-level context: mission, voice, positioning, narrative, pricing |
icp/ |
Ideal Customer Profile segments |
persona/ |
Buyer personas (roles inside an ICP) |
jtbd/ |
Jobs-to-be-done framings |
alternative/ |
Competitors, substitutes, status quo |
client/ |
Customer profiles, case studies, reference accounts |
insight/ |
Market insights and observations |
medium/ |
Channel playbooks (email, LinkedIn, cold call, etc.) |
objection/ |
Objections + responses + proof |
play/ |
GTM plays (signal → audience → channel → sequence → outcome) |
proof/ |
Atomic proof points (metrics, quotes, case data) |
signal/ |
Buying signals and intent triggers |
File conventions
- Filename:
kebab-case.md(e.g.vp-sales-mid-market.md). Use ASCII letters, digits, and hyphens only. - Frontmatter: YAML with
titleanddescriptionon every.md/.mdxfile. This is a strong convention, not enforced — a write with missing, empty, or malformed frontmatter is still committed; it just indexes poorly. The graph readstitle(fallback: filename) andsummary(fallback: first paragraph), notdescription. See Source references and the knowledge graph. - Cross-references:
domain/slugform, no.mdextension (e.g.persona/vp-sales-mid-market). To register as a graph edge, a reference must appear as a wikilink, a markdown link, or a frontmatterreferences:entry (see below) — a baredomain/slugor file path in plain prose is not parsed. - Templates: each domain ships an
_template.md. Read it (cargo-ai context runtime read --path <domain>/_template.md) before authoring a new entry._template.*files are excluded from the graph — never reference them. - Bidirectional links: keep cross-refs symmetric when it makes sense — a
playthat targets apersonashould appear in the persona'sPreferred channelsorHow we landsections when relevant.
Source references and the knowledge graph
The graph is built from every .md, .mdx, .yaml, and .yml file in the repo (any folder; only .git/ is excluded). Each file becomes a node. Edges are created only from these three forms — everything else is invisible to the graph:
-
Frontmatter
references:list (preferred for source citations — keeps prose clean, and the edge carries afrontmatterorigin):--- title: AgoraPulse expansion thesis description: Why the AgoraPulse account is ready for a multi-thread expansion play. references: - outputs/sales-notes/2026-06-05-agorapulse-build-session-1-outcomes.md --- -
A Markdown link in the body — use when the citation needs surrounding prose. Write standard
[label]immediately followed by(path)link syntax pointing at the source file, e.g. an "AgoraPulse session outcomes" anchor linking tooutputs/sales-notes/2026-06-05-agorapulse-build-session-1-outcomes.md. -
Wikilinks in the body (extension optional):
[[outputs/sales-notes/2026-06-05-agorapulse-build-session-1-outcomes]]
Linking rules
- Never cite a source as a bare path in prose. A
Source:line that just mentionsoutputs/sales-notes/foo.mdas plain text is not parsed and creates no edge. Always use one of the three forms above. - Prefer root-relative paths. Paths resolve root-relative first (from the repo root), then relative to the citing file's directory. Root-relative paths work regardless of where the citing document lives.
- Extensions are optional. The resolver auto-tries
.md,.mdx,.yaml,.yml(in that preference order). Including the extension is fine too. - The target must exist. A reference only resolves if the target file is actually in the repo — nonexistent targets become broken edges (dead links in the graph UI). Verify the path before citing it (
cargo-ai context runtime browse --path <dir>). _template.*files are excluded from the graph — don't reference_template.md/.mdx/.yaml/.yml.- YAML data files:
title,summary, andreferencesare read from top-level keys; YAML bodies produce no link edges. - Node title/summary: titles come from frontmatter
title:(fallback: filename); summaries from frontmattersummary:(fallback: the body's first paragraph, truncated to 280 chars). The graph does not readdescription— set asummary:if you want the node summary to differ from the first paragraph. Always settitleso the node is discoverable.
Citing sources in insight / learning documents
When a document has a Source or Evidence section, cite the source files in frontmatter references: — this keeps the prose clean and gives the edges a frontmatter origin. Use inline markdown links when the citation needs surrounding prose.
How to read the context
Start at global/ for company context. Walk icp/ → persona/ → jtbd/ to understand the buyer. Use play/ for outbound motions and objection/ + proof/ for live conversations.
Domain templates
The most commonly authored domains. For domains not shown here (icp/, jtbd/, alternative/, client/, insight/, medium/, signal/), read the in-repo _template.md directly:
cargo-ai context runtime read --path icp/_template.md
cargo-ai context runtime read --path signal/_template.md
# ...
global/_template.md
---
title:
description:
---
## Summary
_One-line version._
## Detail
_Full version. Mission, voice, positioning, narrative, pricing — whatever this entry is._
## Source
_Where this comes from. Founder note, brand doc, board deck, prior conversation._
persona/_template.md
---
title:
description:
---
## Role
- Title:
- Seniority:
- Function:
- Reports to:
## KPIs
-
## Pains
-
## Motivations
-
## Day-to-day
_What this person actually does on a Tuesday._
## Preferred channels
_Cross-ref `medium/...`._
-
## Common objections
_Cross-ref `objection/...`._
-
## How we land
_The angle, the pitch, the moment they get it._
play/_template.md
---
title:
description:
---
## Hypothesis
_Why this play should work. The bet._
## Trigger
_Cross-ref `signal/...`._
-
## Audience
_Cross-ref `icp/...` or `persona/...`._
-
## Channel
_Cross-ref `medium/...`._
-
## Sequence
1.
2.
3.
## Proof
_Cross-ref `proof/...`._
-
## Success metric
_What we measure. Target._
## Owner
_Role accountable for running this._
## Variants
-
proof/_template.md
---
title:
description:
---
## Type
_metric | quote | case | benchmark | screenshot_
## Content
_The actual proof point. Number, quote, fact._
## Source
_Where it comes from. Customer, study, internal data._
## Client
_Optional. Cross-ref `client/...`._
## Context
_What claim this supports. Why we cite it._
## Use cases
_Where this shows up: objections, plays, posts, decks._
-
objection/_template.md
Objections pair a stated buyer concern with the response and the proof that backs it up:
---
title:
description:
---
## Objection
_The buyer's stated concern, in their own words._
## Response
_Our reframe. Short, calm, specific._
## Proof
_Cross-ref `proof/...`._
-
## Personas
_Cross-ref `persona/...` — who raises this most._
-
Authoring rules of thumb
- One concept per file. If you're tempted to add a second
## Personaor a second## Playheading inside one file, you actually want two files. - Title is a label, description is a hook.
titleshows up in lists;descriptionis the one-line that explains why this entry exists. - Cross-refs over duplication. If a fact already lives in
proof/..., link to it from the play or objection rather than re-stating it. - Atomic proof. Each
proof/entry is one fact / quote / metric. Bundled proof points break filtering in the knowledge graph. - Repetition threshold for call-derived claims. A single sales call is anecdote, not evidence. Before promoting an objection / pain / missed-proof claim from call analysis into the context repo, require it to surface across multiple calls. Suggested defaults:
- Call-rich workspaces (≥ 50 transcripts / quarter): 3 occurrences.
- Medium volume: 2 occurrences.
- New / call-poor workspaces (< 10 transcripts): 1 occurrence, and cite the source via frontmatter
references:(or a markdown link) so the citation registers as a graph edge — see Source references and the knowledge graph. The threshold applies to claims, not to facts a call directly confirms (a named customer, a verbatim quote, a competitor explicitly mentioned). Seeexamples/lifecycle.mdfor the full refresh loop.