Vinc
Code and design, one graph
A token changes value, a screen changes shape, a line of code changes with it. The reason is one decision. Here is how to write that decision once and have the code and the design file both point at it, so that six months later "why is this colour so dark" gets the same answer from either side.
The example below is a fictional product, a dashboard called Northwind. Nothing in it is specific to a tool: the design file is any tool whose frames have addresses, the code is any language with comments. What joins them is one id.
1. Write the decision once
The accent colour measured 3.9:1 against the dark header, under the 4.5:1 threshold. Darkening one token brought it to 4.6:1. Four things go into the graph: the token concept, the screen concept, a record holding the measurement, and a decision that says why this value. The decision carries the design file's frame address in props.figma.
Four nodes and three edges travel in one vinc_ingest call. Both ends of an edge have to be in the same call to connect; an edge pointing at a node that is not there is dropped without an error, so read warnings in the response.
vinc_ingest
{
"nodes": [
{ "id": "concept:northwind-accent-token", "type": "concept",
"title": "Northwind accent token", "domain": "northwind/design/tokens",
"one_liner": "The single accent colour, used for links and the primary action." },
{ "id": "concept:northwind-dashboard-header", "type": "concept",
"title": "Northwind dashboard header", "domain": "northwind/design/screens",
"one_liner": "The dark header bar that carries the title, the search box and the account menu." },
{ "id": "record:northwind-accent-contrast-measured", "type": "record",
"title": "Measured 2026-09-01: the accent on the header background is 3.9:1, under the 4.5:1 threshold",
"domain": "northwind/design/tokens",
"props": { "subject_path": "northwind:tokens/design-tokens.json",
"measured_at": "2026-09-01", "measured_ref": "main 4f2c1e0",
"before": "3.9:1", "after": "4.6:1", "threshold": "4.5:1" } },
{ "id": "decision:northwind-accent-darkened-for-contrast", "type": "decision",
"title": "The accent token is darkened one step so it clears 4.5:1 on the header",
"domain": "northwind/design/tokens",
"props": { "date": "2026-09-01",
"figma": "https://www.figma.com/design/FILEKEY/Northwind?node-id=214-88",
"chosen": "darken the accent token from #5B8DEF to #3D6FD1",
"rejected": ["lighten the header background: it is the brand dark",
"keep the value and add an outline: fails on the hover state"] } }
],
"edges": [
{ "from": "record:northwind-accent-contrast-measured",
"to": "concept:northwind-accent-token", "type": "relates_to",
"evidence": "The measurement is of this token's value against the header." },
{ "from": "decision:northwind-accent-darkened-for-contrast",
"to": "concept:northwind-accent-token", "type": "about",
"evidence": "The decision changes this token's value." },
{ "from": "decision:northwind-accent-darkened-for-contrast",
"to": "concept:northwind-dashboard-header", "type": "about",
"evidence": "The header is the surface the contrast was measured on." }
]
}
subject_path, measured_at and measured_ref: the three keys that let two measurements of the same file be compared. When the value changes again, do not delete this record; set its valid_until and attach a new one.2. Point the design file at the graph, and the graph at the file
The decision holds the frame's address. The frame holds one line in its description: the decision's id. Neither tool knows about the other; the id is the seam. When a designer opens the frame and asks why the accent is this dark, that one line is the way to the answer.
This is all the frame description needs to say, and below it is the call that asks by that id. The answer brings the decision's reasoning, the measurement record attached to it, and which concepts the decision is about.
Frame description (in the design file)
Header · accent darkened for contrast
why: decision:northwind-accent-darkened-for-contrast
Ask the graph
vinc_brief question="decision:northwind-accent-darkened-for-contrast"
3. Leave the claim in the code, hand the argument to the graph
Whoever edits the line needs to know what it does and what it must not break. That stays in the comment. Why it came to be this way, what was measured when, what was rejected: that lives in the graph, and the comment names the place by id. What used to be ten lines:
/* Accent colour. Was #5B8DEF until 2026-09-01. Measured against the
header background it came out at 3.9:1, which fails the 4.5:1 AA
threshold for normal text. We considered lightening the header
instead, but that is the brand dark and the marketing site uses it
too. We also tried keeping the value and adding an outline, which
worked at rest but failed on the hover state. So the token itself
was darkened one step to #3D6FD1, which gives 4.6:1. If you change
this, re-measure against the header, not against white. See the
design file, page Header, and the thread in #design from Sept 1. */
--color-accent: #3D6FD1;
becomes two. There is one form for the citation, [[id]], the same brackets for a document id and a node id, and the terminal reads it back with vinc doc get and vinc search.
/* Accent is darkened for contrast on the header. Re-measure against the
header, not white, before changing it. why: [[decision:northwind-accent-darkened-for-contrast]] */
--color-accent: #3D6FD1;
4. Walk it in one call
Both sides end up asking one question: why is this value what it is, and what does it touch. vinc_path answers from the token concept, through the decision, to the screen concept in a single call.
vinc_path from=concept:northwind-accent-token
to=concept:northwind-dashboard-header
concept:northwind-accent-token
← about ─ decision:northwind-accent-darkened-for-contrast
props.figma https://www.figma.com/design/FILEKEY/Northwind?node-id=214-88
attached record:northwind-accent-contrast-measured (3.9:1 → 4.6:1)
─ about → concept:northwind-dashboard-header
5. Which role reads what
Put Agent roles on this flow and each one has a place to read. The designer from the design pack reads the decision and its frame address, and writes a new decision when a value changes. The developer from the software pack follows the citation in the comment to the decision, and when the claim changes, fixes the graph first. The reviewer checks both sides' claims against the graph and labels each one cited, assumed or unsourced. All three write to the graph; none of them touches the file that holds the value.
What to keep straight
- Values in the file the tools read, reasons in the graph. The build reads the token file and the code. The graph holds why. Put a copy of a value in the graph and from that day one of the two is wrong.
- One id is the seam. The line in the frame description, the
[[id]]in the comment and the node id in the graph are the same string. Add no other link. - Measurements are records, choices are decisions. A measured value goes in a record with when and what was looked at; what was chosen and what was rejected goes in a decision. Mix them in one node and every re-measurement rewrites the decision.
- Do not paste the file into the graph. A whole token file or a source file is not a record. If it is needed, it goes in as a document, and concepts are linked through the document.