Skip to content

Commit a6e6fd1

Browse files
committed
Merge branch 'main' into reflective
# Conflicts: # README.md # orchestrator/iteration.py # orchestrator/schemas/campaign.schema.yaml
2 parents a30f09c + 2703822 commit a6e6fd1

22 files changed

Lines changed: 6956 additions & 36 deletions

.claude/commands/index-wiki.md

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
Merge a single campaign's extracted knowledge into the cross-campaign registry.
2+
3+
## Usage
4+
5+
`/index-wiki <campaign-name>` — indexes one campaign into registry.json
6+
7+
## Steps
8+
9+
1. **Resolve campaign**: Use `$ARGUMENTS` as the campaign name. Verify `~/.nous/wiki/campaigns/<campaign-name>/concepts.json` exists.
10+
11+
2. **Read per-campaign files**: From `~/.nous/wiki/campaigns/<campaign-name>/`:
12+
- `concepts.json` — contains `repo_path`, `system_name`, `research_question`, `campaign_name`, `date`, plus `entities`, `concepts`, `parameters`
13+
- `principles.json` — full principle definitions (extract IDs for the registry)
14+
- `dead-ends.json` — refuted approaches
15+
- `frontiers.json` — boundary conditions
16+
- `interactions.json` — untested combinations
17+
18+
3. **Load existing registry**: Read `~/.nous/wiki/registry.json`. If it doesn't exist, initialize:
19+
```json
20+
{"version": 1, "projects": {}}
21+
```
22+
23+
4. **Idempotency check**: Look for this campaign in `projects[repo_path].campaigns[]` by name. If already present, report "Campaign already in registry — skipping" and stop.
24+
25+
5. **Find or create project**: Look up `projects[repo_path]`. If not present, create:
26+
```json
27+
{
28+
"name": "<system_name from concepts.json>",
29+
"campaigns": [],
30+
"entities": []
31+
}
32+
```
33+
34+
6. **Process entities**: For each entity in `concepts.json`:
35+
- Normalize the name (lowercase, strip content in parentheses) for matching
36+
- Check if an entity with the same normalized name exists in `projects[repo_path].entities[]`
37+
- If yes: add this campaign name to its `campaigns[]` array (if not already there)
38+
- If no: assign new ID `E-{max_entity_id + 1}`, create entry:
39+
```json
40+
{"id": "E-N", "name": "<entity name>", "aliases": [], "campaigns": ["<campaign-name>"]}
41+
```
42+
- Track the max entity ID across all projects globally (IDs are globally unique)
43+
44+
7. **Build campaign object**: Create the campaign entry for the registry:
45+
```json
46+
{
47+
"name": "<campaign_name>",
48+
"date": "<date>",
49+
"research_question": "<research_question>",
50+
"concepts": [],
51+
"parameters": [],
52+
"principles": [],
53+
"dead_ends": [],
54+
"frontiers": [],
55+
"interactions": []
56+
}
57+
```
58+
59+
- **Concepts**: For each concept in `concepts.json`, assign ID `C-{max+1}` and add `{"id": "C-N", "name": "<concept name>"}` to the campaign's `concepts[]`
60+
- **Parameters**: For each parameter in `concepts.json`, assign ID `P-{max+1}` and add `{"id": "P-N", "name": "<parameter name>"}` to the campaign's `parameters[]`
61+
- **Principles**: Read `principles.json`, add each principle's ID string (e.g., "RP-1") to the campaign's `principles[]` array
62+
- **Dead-ends**: For each entry in `dead-ends.json`, assign ID `DE-{max+1}` and add `{"id": "DE-N", "title": "<title>"}` to the campaign's `dead_ends[]`
63+
- **Frontiers**: For each entry in `frontiers.json`, assign ID `F-{max+1}` and add `{"id": "F-N", "title": "<title>"}` to the campaign's `frontiers[]`
64+
- **Interactions**: For each entry in `interactions.json`, assign ID `I-{max+1}` and add `{"id": "I-N", "title": "<title>"}` to the campaign's `interactions[]`
65+
66+
8. **Add campaign to project**: Append the campaign object to `projects[repo_path].campaigns[]`.
67+
68+
9. **Recompute entity clusters**: Using ALL entities in `projects[repo_path].entities[]` and their definitions from per-campaign `concepts.json` files:
69+
70+
a. For each entity, gather its definition from the campaign(s) that define it (read `~/.nous/wiki/campaigns/<campaign>/concepts.json``entities[]` → match by name). If an entity appears in multiple campaigns, concatenate definitions with ` | `.
71+
72+
b. Semantically group entities by functional role/purpose into clusters. Rules:
73+
- Min 2 entities per cluster, max 10
74+
- Max 20 clusters total per project — if grouping would exceed 20, merge the smallest/most-similar clusters
75+
- Each entity belongs to at most one cluster (singletons are valid — omit them)
76+
- Labels: 2-4 words, Title Case, describe the functional group
77+
78+
c. Assign sequential IDs `EC-1`, `EC-2`, etc. Set `projects[repo_path].entity_clusters` to:
79+
```json
80+
[{"id": "EC-1", "label": "...", "entities": ["E-4", "E-5", "E-6"]}, ...]
81+
```
82+
83+
d. **CRITICAL**: This step ONLY writes the `entity_clusters` field. Do NOT modify `name`, `campaigns`, `entities`, or any other field on the project or registry.
84+
85+
10. **Write registry.json**: Write the updated registry to `~/.nous/wiki/registry.json` with 2-space indentation.
86+
87+
11. **Report**: Print the registry path and a summary of what was added (counts of entities, concepts, parameters, principles, dead-ends, frontiers, interactions).
88+
89+
## ID Assignment Rules
90+
91+
- IDs are **globally unique** across all projects and campaigns
92+
- To find the next ID for a type (e.g., "C-"), scan ALL projects and campaigns in the registry for the maximum existing ID of that type, then increment
93+
- Entity IDs (E-N) are unique per-project in practice but globally unique in assignment
94+
- Principle IDs (RP-N) are NOT reassigned — they keep their original campaign-local IDs
95+
96+
## Deduplication Rules
97+
98+
- **Entities**: Match by normalized name (lowercase, strip parenthetical suffixes). If matched, add campaign to existing entity's `campaigns[]` array.
99+
- **Everything else** (concepts, parameters, dead-ends, frontiers, interactions): Always create new entries. Different campaigns may have similar-sounding entries that are contextually distinct. Never deduplicate these across campaigns.
100+
101+
## Important Rules
102+
103+
- This skill only reads from `~/.nous/wiki/campaigns/` — it never reaches back to source repos
104+
- This is the ONLY skill that writes to `registry.json`
105+
- All metadata (`repo_path`, `system_name`, `research_question`) comes from the per-campaign `concepts.json`, which was populated by `/post-campaign` from the source `campaign.yaml`
106+
- Process one campaign at a time (read registry → modify → write) to prevent conflicts
107+
- `entity_clusters` is the ONLY registry field that is recomputed (not appended). It is fully replaced each time a new campaign is indexed. All other data is strictly append-only.

0 commit comments

Comments
 (0)