Umbrella skill for contributing durable knowledge to a Cogni node hub. Triggers when an agent has — or is about to research — context worth compounding for future agents/humans, AND the knowledge is durable enough to survive the syntropy bar. Routes to the right sub-skill by content shape (falsifiable prediction → `edo-loop`; visual for humans → `dolt-human-visuals`; AI-readable text → direct contribution). Use whenever you'd otherwise drop a research finding into a chat log or PR description...
4 stars
0 votes
0 copies
1 view
Added September 9, 2026
researchgobashsqlnodeexpressapi
Works with
api
Security analysis
B88/100
criticalSends environment variables or credentials to an external URL
Installs into .claude/skills of the current project.
Are you the author of Contribute Knowledge To Cogni?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/cogni-dao-contribute-knowledge-to-cogni)
---
name: contribute-knowledge-to-cogni
description: Umbrella skill for contributing durable knowledge to a Cogni node hub. Triggers when an agent has — or is about to research — context worth compounding for future agents/humans, AND the knowledge is durable enough to survive the syntropy bar. Routes to the right sub-skill by content shape (falsifiable prediction → `edo-loop`; visual for humans → `dolt-human-visuals`; AI-readable text → direct contribution). Use whenever you'd otherwise drop a research finding into a chat log or PR description that should outlive the session. RARE by design — most agent context dies with the session; only what compounds earns an entry.
---
# contribute-knowledge-to-cogni — route any knowledge contribution
> Knowledge entries are precious. The right question is rarely "what do I write?" — it's "should I write anything, or refine what already exists?"
## ONE PRINCIPAL · ONE OPEN CONTRIBUTION · refine via `/commits` — never fork
This is the rule the rest of the skill hangs on. Get it wrong and you sprawl the
inbox with N single-commit branches for one unit of work (the noob failure).
- **One principal.** Reuse your saved API key. Do **not** register a fresh agent
per write — each registration is a new principal, and the inbox fills with
orphan one-commit contributions nobody can attribute to one author.
- **One open contribution at a time.** A principal holds a single open
`contrib/*` branch. Everything you contribute this session lands on it.
- **First write creates the branch; every write after that appends.**
`POST /contributions` **always forks a new branch** — call it exactly once.
All subsequent edits (a new entry _or_ a refinement) go to
`POST /contributions/{id}/commits`. Re-POSTing `/contributions` is the
fracturing bug: it does **not** compound, it spawns a second branch.
- **Start something genuinely unrelated?** Close the current one first
(`POST /contributions/{id}/close`), then create. Don't run two open branches.
> Asymmetry to remember: the **EDO endpoints** (`/api/v1/edo/*`) auto-compound
> onto your one open contribution server-side. The **raw `/contributions`**
> endpoint does **not** — you compound it yourself by using `/commits`.
## Action hierarchy (mirrors `knowledge-syntropy-expert`)
Walk top-to-bottom. **Most agent work stops at step 1.**
1. **STAY SILENT.** Is this context: ephemeral (dies with session), routine work-item state, an in-PR finding, an obvious factual lookup, OR something an existing entry already says? → **write nothing.** Knowledge entries are precious; sprawl is the failure mode. **≥80% of contributable-feeling moments belong here.**
2. **RECALL — both planes.** (a) The **merged** plane: `/knowledge?mode=browse` filtered by domain, or `core__knowledge_search`. (b) **Your own open contribution _branch_**: `GET /contributions?state=open` for the id, then **`GET /contributions/{id}/diff` to read the entries already on it.** Branch-local entries do **not** appear in `/knowledge?domain=` (it returns merged-`main` only) — so an agent who recalls the merged plane alone will re-discover, re-author, or outright deny knowledge it wrote minutes ago on its own branch. Read the branch before you write or before you answer "does X exist / is it linked." Cite the siblings you find; append rather than fork.
3. **REFINE.** Found a related entry that's slightly off, stale, or bloated? **Sharpen it in place** via an `op: update` edit. Shorter + sharper + raises confidence. **This is the most valuable knowledge move; most contribution work should look like this.**
4. **CITE.** Your claim is a relationship between existing atoms or an example of one? Add a `citation` edge — `supports`, `contradicts`, `extends`, `supersedes`. Or write a sibling atom that cites the parent. Never inline "companion to X" prose. **Cite across planes freely:** an entry on your open branch may cite one already merged to `main` (cross-plane) — this resolves correctly and the edge becomes live in `main`'s DAG when your contribution merges. (Before bug.5024 this silently 500'd; it now works, so don't avoid citing merged atoms from a long-lived compounding branch.) **Work-item links are also citations:** use `citationType: "tracks"` to connect exactly one work item (`task.*`, `bug.*`, `spike.*`, `story.*`, or `subtask.*`) with one knowledge entry already present on `main`; both endpoints are validated before the edge is accepted.
5. **WRITE ATOMIC.** No existing atom fits AND the claim earns its keep → file new entry. See routing below for which entry type / sub-skill. **Nearly always cite at least one existing entry in the same edit** (`supports`/`extends`/`contradicts`/`supersedes`) — a new atom should compound onto the graph, not land as an island. RECALL almost always surfaces a parent or sibling to link; a brand-new entry with zero edges is the silent failure mode that keeps the hub a flat document store instead of a compounding DAG.
6. **EXTEND.** Anti-pattern. Don't bloat an existing atom to cover more cases — write a sibling, cite the parent.
## Routing by content shape
After RECALL confirms a new write is genuinely needed, pick exactly one path:
| Content shape | Audience | Entry type | Sub-skill |
| ---------------------------------------------------------------------------------------- | -------- | ----------------------------------------------------------------------------------- | ------------------------------------------------------ |
| Falsifiable prediction that resolves in a later session and shapes future agent action | agent | `hypothesis` / `decision` / `outcome` (atomic chain) | [`edo-loop`](../edo-loop/SKILL.md) |
| Visual artifact (diagram, scorecard, roadmap, status grid, design diff) for human review | human | `html` (sandboxed iframe) | [`dolt-human-visuals`](../dolt-human-visuals/SKILL.md) |
| Atomic factual claim with provenance, recallable by future agent search | agent | `observation` / `finding` / `conclusion` / `rule` / `scorecard` / `skill` / `guide` | direct (this skill) |
**One entry, one shape.** Don't mix — a "scorecard with embedded prediction" is two entries, one cites the other. But both still land as **edits on your one open contribution** — separate shape ≠ separate branch.
## EDO vs knowledge entry vs spec — what truth goes where
Three durable homes. Pick by the _shape of the truth_, not by which is easiest.
| You have… | Home | Why |
| ------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| As-built fact about how the system works **right now** — architecture, a contract, an invariant a future agent needs as ground truth | **`docs/spec/*` in the repo** (refine an existing spec; ship it in the PR) | `SPECS_ARE_AS_BUILT`. Versioned with the code, reviewed in the PR that makes it true. Not in the hub. |
| Atomic learning with provenance — "we found X", a rule, a scorecard — **not** a prediction, **not** architecture | **knowledge entry** (this skill) | Recallable by agent search, confidence-rated, compounds in the Dolt hub. |
| Falsifiable **prediction** that resolves in a **later** session, is contestable, and changes what the next agent does | **EDO chain** ([`edo-loop`](../edo-loop/SKILL.md)) | Time-bound belief → action → outcome; confidence recomputes when the outcome lands. |
**EDO linked to a spec** — when your prediction is _about_ a spec'd subsystem:
- The **spec** stays the as-built description (what the system does).
- The **EDO** carries the time-bound belief (whether a change moves a metric).
- Wire them, don't merge them: `hypothesize.content` references the spec id; the `decide` row's `source_ref` points at the PR that changes the spec'd behavior; the `outcome` reads the deployed system at `sha:<deployed>`.
- Don't fold the prediction into the spec (specs aren't predictions). Don't restate the spec inside the EDO (cite it).
Tie-breakers:
- Tempted to write a `docs/spec/knowledge-*` doc for a one-off learning? Almost always wrong — refine a hub entry. Specs are for durable as-built contracts, not findings.
- Tempted to file a `finding` for a prediction because EDO feels heavy? If it's falsifiable + session-separated + contestable, it's an EDO **or it's silence** — not a finding.
Text entry types render their `content` as **GFM markdown** in the human UI (structure it — see "Format the `content` field"). `html` is reserved for visual artifacts markdown can't express.
## Picking the right node
Cogni nodes own niche hubs. Pick by primary subject:
- **operator** (`https://cognidao.org` / `https://test.cognidao.org`) — cross-cutting infrastructure, knowledge platform itself, syntropy, deploy + flight, work-item lifecycle, governance. **Default when in doubt.**
- Each node owns its own domain. derive the node set — `for f in infra/catalog/*.yaml; do grep -q '^type: node' $f && basename $f .yaml; done` — never a hand-typed list (Dolt `operator-node-catalog`: "the roster is LIVE STATE"); a node's hub lives at its own host. (A hand-typed list here previously named `resy`, a node that never existed.)
- Other nodes — see each node's charter.
If a claim is genuinely cross-node (e.g. "Doltgres `WITH RECURSIVE` works at 1k rows"), file once on **operator** and cite from per-node hubs as they need it. Don't duplicate.
## Picking the right domain
`domain` is a registered FK on every entry (DOMAIN_FK_ENFORCED_AT_WRITE). Pick from existing — register a new one ONLY if no existing domain fits and the new one will accumulate ≥5 entries.
Common operator-node domains (seeded): `meta`, `infrastructure`, `prediction-market`, `governance`, `reservations`.
If unsure → use `meta` (knowledge about the knowledge system itself) or the closest existing match. Register new via `POST /api/v1/knowledge/domains` (bearer or session auth, post-W2).
## Mechanics — direct text path
For text entry types (`observation`/`finding`/`conclusion`/`rule`/`scorecard`/`skill`/`guide`). For `html` use `dolt-human-visuals`; for EDO chains use `edo-loop`. Full envelope contract: [`docs/design/knowledge-contribution-api.md`](../../../docs/design/knowledge-contribution-api.md).
```bash
KEY=$(grep -E "^COGNI_API_KEY_TEST=" .env.cogni | cut -d= -f2- | tr -d "\"") # reuse your ONE key
BASE=https://test.cognidao.org # or production cognidao.org
```
**Step 1 — recall your open contribution AND read what's already on its branch:**
```bash
CID=$(curl -sS "$BASE/api/v1/knowledge/contributions?state=open&limit=20" \
-H "Authorization: Bearer $KEY" | jq -r '.contributions[0].contributionId // empty')
# MANDATORY when CID exists: read the entries already on YOUR branch. These are
# NOT in /knowledge?domain= (merged-main only) — skip this and you'll re-author
# or deny knowledge you wrote this session. Cite/refine these siblings.
[ -n "$CID" ] && curl -sS "$BASE/api/v1/knowledge/contributions/$CID/diff" \
-H "Authorization: Bearer $KEY" | jq -r '.entries[] | "\(.rowId): \((.after // .before).title)"'
```
**Step 2 — only if you have none open, create ONCE and capture the id:**
```bash
CID=$(curl -sS -X POST "$BASE/api/v1/knowledge/contributions" \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{
"message": "<one-line intent for this unit of work>",
"edits": [{
"op": "insert",
"entry": {
"id": "<kebab-slug, ≤4 dash segments>",
"domain": "<registered>",
"title": "<use-when-X framing>",
"content": "<atomic claim with provenance>",
"entryType": "finding",
"tags": ["<short>", "<discoverable>"]
}
}]
}' | jq -r .contributionId)
```
**Step 3 — every further edit appends to that SAME branch via `/commits`:**
```bash
# Add another atom, refine a row you created earlier on this branch, or delete —
# all on the open contribution. NEVER POST /contributions again for this work.
curl -sS -X POST "$BASE/api/v1/knowledge/contributions/$CID/commits" \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{
"message": "append: <what this commit changes>",
"edits": [{ "op": "insert", "entry": { ... } }]
}'
```
One POST can carry a **mixed-op batch** (`insert` + `update` + `delete`, up to 50) in a single commit when the changes belong together — that's one review for one coherent unit, not N branches.
**Work-item↔knowledge tracking links.** Use a `cite` edit with
`citationType: "tracks"` when a work item is the operational owner of a
knowledge entry, or when a knowledge entry explains/proves a work item. The edge
must connect exactly one work-item id and one merged knowledge id; branch-local
knowledge rows are not accepted for `tracks` because work-item detail pages read
the merged DAG.
```bash
curl -sS -X POST "$BASE/api/v1/knowledge/contributions/$CID/commits" \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{
"message": "link story.5017 to knowledge invariant",
"edits": [{
"op": "cite",
"citingId": "story.5017",
"citedId": "<merged-knowledge-id>",
"citationType": "tracks",
"context": "story.5017 implements and validates this knowledge invariant"
}]
}'
```
Do **not** add work-item link columns or duplicate the relationship in work
metadata. The `citations` row is the source of truth and renders from both the
knowledge and work-item detail surfaces after merge.
**Two distinct "refine" cases — don't conflate them:**
| You want to refine… | How |
| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| a row you wrote earlier **on your open branch** | `POST /contributions/{id}/commits` with `{op:"update", targetRowId, entry}` — `targetRowId` resolves on the branch |
| an entry **already merged to `main`** | `POST /contributions` once with `{op:"update", targetRowId:<main id>}`, then keep refining **that** via `/commits` |
### Edit ops + the three constraints that bite
`KnowledgeContributionEditSchema` is a discriminated union of **exactly four** ops
(`packages/knowledge-store/src/domain/contribution-schemas.ts`) — anything else is
HTTP 400 `invalid_union` / "No matching discriminator":
- `{op:"insert", entry}` · `{op:"update", targetRowId, entry}` · `{op:"delete", targetRowId, reason}` (**`reason` is required**, 1–512 chars) · `{op:"cite", citingId, citedId, citationType, context?}` (self-citation — `citingId === citedId` — is rejected at the wire). The API verb is literally `delete`; the syntropy bar for _when_ to remove an entry is a separate judgement call (see `knowledge-syntropy-expert`).
- **Referential integrity on delete.** Deleting a row that anything cites fails **409**: `cannot delete '<id>': cited by <list>. Remove or repoint those edges first, or refine the entry in place.` The dead row's own _outbound_ edges cascade; inbound edges never dangle.
- **`tracks` endpoints must already be on `main`.** A `tracks` edge pointing at a **branch-local** knowledge row fails **404** `{"code":"cited_not_found"}` — work-item detail pages read the merged DAG. Cross-plane the other way works: a branch entry citing a merged entry resolves fine and goes live in `main`'s DAG on merge.
- **`op:update` cannot rename a row id.** `targetRowId` is the `WHERE` key and `entry.id` is ignored, so a slug can never change in place. Renaming a **cited** entry therefore needs multiple sequential merges (insert new → merge → repoint edges → delete old) — prefer refining in place.
- **Consequence, stated plainly: supersede+repoint of a cited entry is impossible inside one contribution.** Don't plan a batch around it; refine the entry in place instead.
Verified empirically against `https://cognidao.org` on 2026-09-16.
## Format the `content` field as Markdown
The human UI renders `content` for text entries through `<Markdown>` (GFM: headings, **bold**, lists, tables, `code`, links). The same bytes stay plain-text for AI search + embeddings. **One source of truth, both audiences** — so write structured markdown, not a prose blob. A wall of prose renders as a wall of prose; it's the failure mode in most existing entries.
Lead with a **`use-when` / claim line in bold**, then structure the evidence. Reach for a table when you have ≥2 parallel facts.
**❌ Prose blob — unscannable, renders identically to its raw source:**
```
We found that the Doltgres adapter cannot use postgres.js extended protocol
because prepared statements break on Doltgres, so the adapter uses sql.unsafe()
with manual escapeValue and JSONB containment operators like @> and ILIKE are
not supported which means queries must avoid them.
```
**✅ Structured markdown — same claim, scannable, renders as formatted HTML:**
```markdown
**Use when:** writing a query adapter against Doltgres.
Doltgres breaks `postgres.js` **extended protocol** (prepared statements fail),
so the adapter routes around it:
| Constraint | Workaround |
| ------------------------- | --------------------------------------- |
| No prepared statements | `sql.unsafe()` + manual `escapeValue()` |
| No JSONB `@>` containment | rewrite as key extraction |
| No `ILIKE` | `LOWER(col) LIKE` |
Source: `spike.0229` — 13 integration tests passing.
```
A `scorecard` entry is a markdown table of `dimension | us | optimal | gap` rows. A `rule` is a bold imperative + a short rationale list. A `guide` is `##` sections with fenced commands. Keep it atomic — structure sharpens one claim; it is **not** license to lengthen.
**Markdown text vs `html` entry.** Markdown covers ~all knowledge: headings, tables, lists, code. Reach for an `html` entry (via [`dolt-human-visuals`](../dolt-human-visuals/SKILL.md)) **only** when the artifact is genuinely visual — an SVG architecture diagram, a chart, a status grid markdown can't express. Default is markdown text; `html` is the rare escape hatch, not "anything a human reads." Raw HTML is **not** rendered in the markdown lane (it's escaped) — full HTML only runs in the sandboxed-iframe `html` path.
## Confidence — what you set vs what the system computes
Don't set `confidencePct` on the request unless you have a defensible reason. Initial confidence comes from your principal's `sourceType` (agent=30 = draft; human=70). Recompute raises it as citation evidence lands. Manual overrides undermine the recompute contract — let the resolver do its job.
## When to invoke this skill
- Before opening any `core__knowledge_write` tool call
- Before posting to `/api/v1/knowledge/contributions` directly
- When tempted to "just write it in the PR description" but the claim is reusable
- When tempted to write a doc under `docs/spec/knowledge-*` — almost never the right home; refine an existing knowledge entry or write a new atomic one in the hub
## Anti-patterns
- **Re-POSTing `/contributions` for related work instead of appending via `/commits`** — the fracturing failure: N single-commit branches for one unit of work (and an inbox no human wants to triage).
- **Recalling the merged plane only — never reading your own open branch.** `/knowledge?domain=` returns merged-`main`; your `contrib/*` branch entries are invisible to it. Answering "does X exist / is it linked" or deciding to write _without_ `GET /contributions/{id}/diff` is how an agent denies or duplicates knowledge it authored minutes ago (the exact failure that prompted this rule).
- **Registering a fresh agent key per contribution** — multiplies principals; reuse your one saved key.
- Filing a new entry when RECALL would surface an existing match
- **Filing a new atom with zero citation edges — the island failure.** A new entry should nearly always `cite` a parent/sibling RECALL surfaced (cross-plane to merged atoms works); islands don't compound and leave the hub a flat document store
- **Linking work items outside `citations`** — work↔knowledge relationships use one `tracks` edge, not duplicated columns, tags, or prose.
- Writing a `content` prose blob instead of structured markdown (headings / bold lead / table / list) — renders as an unscannable wall; see "Format the `content` field"
- Reaching for `html` for ordinary human-facing content that a markdown table or list expresses fine — `html` is the rare visual escape hatch (SVG / chart), not the default for "a human reads it"
- Filing a falsifiable prediction as `finding` to avoid EDO overhead — use `edo-loop` or stay silent
- Authoring a genuinely visual artifact (diagram, chart) as plain text (loses the styling contract from `knowledge-html-style.md`)
- Putting a one-off learning in `docs/spec/*` — specs are durable as-built contracts, not findings
- Setting `confidencePct` manually because the draft (30) looked low
- Duplicating cross-node — file once, cite from other nodes
## Cross-references
- `knowledge-syntropy-expert` — action hierarchy + REFINE_OVER_EXTEND + RECALL_BEFORE_WRITE
- `edo-loop` — falsifiable predictions (auto-compounds onto your one open contribution)
- `dolt-human-visuals` — HTML entries for human review
- `contribute-to-cogni` — separate skill for **code** contributions (PRs); this skill is for **knowledge** contributions
- `docs/spec/knowledge-syntropy.md` — schema, invariants, write/read protocol
- `docs/spec/knowledge-html-style.md` — tokens + utility classes for `entryType: html`
- `docs/design/knowledge-contribution-api.md` — full request/response envelope contract (`/contributions` create vs `/commits` append)