---
name: emerge
description: "Clusters KnowledgeDocument and Section nodes that have no Concept parent yet, names each cluster, and proposes a Concept node through the operator-approval write path. Run when the operator types `/emerge` or asks 'what themes are emerging in my notes', 'find unclustered knowledge', 'what haven't I connected yet'. Each proposal requires operator approval before any write."
---

# Emerge

This skill surfaces unnamed clusters of knowledge already in the operator's graph — documents and sections that share a theme but have no Concept node connecting them yet. For each cluster it proposes a name and routes the write through the operator-approval gate. It never writes without approval.

## When to run

Run when the operator wants to discover unclustered themes: `/emerge`, "what themes are emerging in my notes", "find unclustered knowledge", "what haven't I connected yet". Run on demand; do not run as a routine maintenance pass.

## Method

1. **Retrieve candidates.** Issue `memory-search` with a broad query ("recent knowledge notes"), `labels: ["KnowledgeDocument", "Section"]`, `limit=50, expandHops=0`. The `expandHops=0` keeps output compact — deep neighborhood context is not needed at retrieval time.

2. **Filter already-clustered.** From the returned nodes, exclude any node that has a `:RELATES_TO` edge to a `:Concept` node visible in its neighborhood. If unsure whether a node is clustered, err on the side of inclusion — the operator will skip it in the approval step.

3. **Group by similarity.** Cluster the remaining nodes by semantic similarity: nodes whose content shares a clear theme. Clusters of fewer than 3 nodes are set aside as "too small to cluster" and listed separately at the end.

4. **Name each cluster.** Compose a short noun-phrase name (1–4 words) from the highest-weighted terms shared across the cluster's nodes. The name should generalise the cluster, not copy a document title.

5. **Identify the parent.** For each cluster, identify the most likely `:Project` or `:LocalBusiness` parent — the entity most cluster members are already connected to. Name it in the proposal row. If no clear parent is identifiable, ask the operator before presenting the proposal.

6. **Present proposals one at a time.** The operator picks one of three actions per proposal: **wire** (write the `:Concept` and edges), **skip**, or **rename** (operator supplies a new name; re-propose with the new name before proceeding).

## Write shape (per approved cluster)

```
memory-write {
  label: "Concept",
  properties: {
    name: "<cluster name>",
    description: "<one-sentence description of what the cluster members share>",
    accountId: "<accountId>",
    createdByAgent: "emerge",
    createdAt: datetime()
  },
  parent: { elementId: "<project-or-localbusiness-elementId>", edgeType: "PART_OF" },
  relationships: [
    { type: "RELATES_TO", direction: "out", target: "<member elementId>" }
    ... one per cluster member
  ]
}
```

Apply each approved write before presenting the next proposal. Never batch-write.

## Output

Per proposal row:
```
**[N] <cluster name>**
Members (<count>): <title-1> (ID: `<id>`), <title-2> (ID: `<id>`), ...
Parent: <parent entity name>
Description: <one-sentence>
→ wire / skip / rename?
```

End-of-run summary (after all proposals are decided):
```
<K> clusters proposed, <A> wired, <S> skipped, <R> renamed.
Too small to cluster: <title-1>, <title-2> (list of 1–2 node sets, if any)
```

## Failure modes

- **All nodes already clustered.** Report "All retrieved knowledge is already connected to a Concept node. Nothing to propose." Do not re-run.
- **No nodes retrieved.** Report "No KnowledgeDocument or Section nodes found. Nothing to cluster."
- **`memory-write` failure mid-batch.** Stop. Report which clusters were wired before the failure and which were not.

## Observability

Emit one log line per proposed cluster:
```
[memory-thinking] skill=emerge clusterSize=<N> proposedConcept=<name> elapsedMs=<N>
```

`clusterSize` is the number of member nodes in that cluster. `elapsedMs` is measured from skill invocation to the moment the proposal is presented to the operator (not including operator decision time).

If no clusters are proposed (all nodes already clustered, or no nodes retrieved), emit one line to mark the invocation:
```
[memory-thinking] skill=emerge clusterSize=0 proposedConcept=none elapsedMs=<N>
```

Absence of any `skill=emerge` log line means the skill was not invoked (operator typo or routing miss).
