helixevo 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/README.md +15 -2
- package/dashboard/app/api/ontology/route.ts +89 -0
- package/dashboard/app/coevolution/client.tsx +11 -1
- package/dashboard/app/coevolution/page.tsx +3 -2
- package/dashboard/app/commands/page.tsx +23 -0
- package/dashboard/app/guide/page.tsx +15 -1
- package/dashboard/app/ontology/client.tsx +247 -0
- package/dashboard/app/ontology/page.tsx +9 -0
- package/dashboard/app/page.tsx +12 -2
- package/dashboard/app/topology/client.tsx +1 -0
- package/dashboard/components/sidebar-nav.tsx +1 -0
- package/dashboard/lib/data.ts +325 -4
- package/dist/cli.js +614 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,17 @@ All notable changes to HelixEvo are documented here.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.5.0] - 2026-03-24
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- New `helixevo ontology` command for ontology frontier status, refresh, review, and deprecation control
|
|
11
|
+
- New `~/.helix/ontology/` persistence model with kernel snapshot, frontier concepts, approved extensions, review decisions, and native ontology change events
|
|
12
|
+
- New `/ontology` dashboard route and `/api/ontology` operator control surface for governed semantic review
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
- Overview semantic-backbone summaries now expose hybrid native + derived ontology state instead of only compatibility-era framing
|
|
16
|
+
- Dashboard Guide, Commands, and README now document ontology frontier control alongside co-evolution and topology control
|
|
17
|
+
|
|
7
18
|
## [0.4.1] - 2026-03-24
|
|
8
19
|
|
|
9
20
|
### Changed
|
package/README.md
CHANGED
|
@@ -89,6 +89,7 @@ helixevo dashboard
|
|
|
89
89
|
| `helixevo generalize` | Promote cross-project patterns ↑ |
|
|
90
90
|
| `helixevo specialize --project <name>` | Create project-specific skills ↓ |
|
|
91
91
|
| `helixevo graph` | View skill network in terminal |
|
|
92
|
+
| `helixevo ontology` | Refresh, review, and govern ontology frontier concepts |
|
|
92
93
|
| `helixevo topology` | Prepare, apply, roll back, and inspect reviewed topology execution |
|
|
93
94
|
| `helixevo research` | Proactive web research for skill improvement |
|
|
94
95
|
| `helixevo dashboard [--port <n>]` | Open web dashboard, preferring localhost:3847 and falling forward if occupied |
|
|
@@ -109,6 +110,10 @@ helixevo graph --mermaid # Open in browser as Mermaid diagram
|
|
|
109
110
|
helixevo graph --obsidian ~/vault # Sync to Obsidian vault
|
|
110
111
|
helixevo graph --rebuild # Re-infer relationships (LLM call)
|
|
111
112
|
helixevo graph --optimize # Detect structural candidates + refresh topology review queue
|
|
113
|
+
helixevo ontology --status # Show ontology kernel / frontier / extension state
|
|
114
|
+
helixevo ontology --refresh # Derive frontier concepts from recurring evidence
|
|
115
|
+
helixevo ontology --review <id> --decision promote
|
|
116
|
+
# Promote a reviewed frontier concept into approved extensions
|
|
112
117
|
helixevo topology --status # Show reviewed topology execution state
|
|
113
118
|
helixevo topology --prepare <id> # Prepare an accepted topology candidate
|
|
114
119
|
helixevo topology --apply <id> # Apply a safe prepared topology plan
|
|
@@ -144,7 +149,13 @@ All data is stored in `~/.helix/`:
|
|
|
144
149
|
├── topology-apply-plans.json # Prepared reviewed topology plans
|
|
145
150
|
├── topology-executions.jsonl # Prepared/applied/rolled-back execution ledger
|
|
146
151
|
├── topology-artifacts.jsonl # Evidence artifacts for reviewed structural execution
|
|
147
|
-
├── evolution-artifacts.jsonl # Evolution evidence artifacts
|
|
152
|
+
├── evolution-artifacts.jsonl # Evolution + ontology-review evidence artifacts
|
|
153
|
+
├── ontology/
|
|
154
|
+
│ ├── kernel.json # Materialized ontology kernel snapshot
|
|
155
|
+
│ ├── extensions.json # Approved ontology extensions
|
|
156
|
+
│ ├── frontier.json # Provisional frontier concepts awaiting review
|
|
157
|
+
│ ├── reviews.jsonl # Ontology review decisions
|
|
158
|
+
│ └── change-log.jsonl # Native ontology change events
|
|
148
159
|
├── frontier.json # Pareto frontier (top-k configurations)
|
|
149
160
|
├── evolution-history.json # All evolution runs + proposals
|
|
150
161
|
├── skill-tests.jsonl # Regression test cases
|
|
@@ -171,9 +182,10 @@ helixevo dashboard --port 3900
|
|
|
171
182
|
```
|
|
172
183
|
|
|
173
184
|
**Tabs:**
|
|
174
|
-
- **Overview** — Premium control cockpit with frontier signals, brain foundation, semantic backbone, pressure counts, topology review visibility, and prepared/applied structural state
|
|
185
|
+
- **Overview** — Premium control cockpit with frontier signals, brain foundation, semantic backbone, pressure counts, ontology frontier visibility, topology review visibility, and prepared/applied structural state
|
|
175
186
|
- **Skill Network** — Interactive graph, premium inspector, co-evolution routing signals, and topology review/execution handoff links
|
|
176
187
|
- **Co-Evolution** — Operator cockpit for routed pressure response, governance mode visibility, promotion queues, transfer evidence, and topology handoff
|
|
188
|
+
- **Ontology** — Semantic control surface for kernel visibility, frontier concept review, approved ontology extensions, and native ontology change events
|
|
177
189
|
- **Topology** — Governance steering plus a persistent operator pipeline for review → prepare → apply → rollback across merge / split / promote / rewire / consolidate candidates
|
|
178
190
|
- **Projects** — Project intake studio, live project analysis, gap routing, per-project pressure hotspots, and promotion feeders
|
|
179
191
|
- **Evolution** — Timeline of evolution runs with judge scores, artifact provenance, and activation-aware context
|
|
@@ -212,6 +224,7 @@ Failures → Cluster → Propose → Replay → Multi-Judge → Regression → C
|
|
|
212
224
|
|
|
213
225
|
**Brain foundation:**
|
|
214
226
|
- **Ontology** defines the stable semantic kernel for skills, projects, tasks, capabilities, artifacts, and mutations.
|
|
227
|
+
- **Ontology frontier and extensions** let new semantic concepts emerge as provisional hypotheses, pass explicit review, and become approved extensions without free-form drift.
|
|
215
228
|
- **Activation traces** record which skills and gaps were active during capture and project analysis.
|
|
216
229
|
- **Pressure signals** turn failures and project gaps into explicit adaptation demand.
|
|
217
230
|
- **Pressure interventions** record how HelixEvo responded across research, specialize, evolve, generalize, and manual-review lanes.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server'
|
|
2
|
+
import { spawn } from 'child_process'
|
|
3
|
+
import { existsSync } from 'fs'
|
|
4
|
+
import { join } from 'path'
|
|
5
|
+
import { loadOntologyControlSummary } from '@/lib/data'
|
|
6
|
+
|
|
7
|
+
export const dynamic = 'force-dynamic'
|
|
8
|
+
|
|
9
|
+
function resolveOntologyRunner(): { cmd: string; argsPrefix: string[] } {
|
|
10
|
+
const candidates = [
|
|
11
|
+
join(process.cwd(), '..', 'dist', 'cli.js'),
|
|
12
|
+
join(process.cwd(), 'dist', 'cli.js'),
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
for (const candidate of candidates) {
|
|
16
|
+
if (existsSync(candidate)) return { cmd: process.execPath, argsPrefix: [candidate] }
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return { cmd: 'helixevo', argsPrefix: [] }
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function runOntologyCommand(args: string[]): Promise<{ success: boolean; output: string }> {
|
|
23
|
+
return new Promise((resolve) => {
|
|
24
|
+
const runner = resolveOntologyRunner()
|
|
25
|
+
const child = spawn(runner.cmd, [...runner.argsPrefix, 'ontology', ...args], {
|
|
26
|
+
env: { ...process.env },
|
|
27
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
let output = ''
|
|
31
|
+
child.stdout?.on('data', (chunk: Buffer) => {
|
|
32
|
+
output += chunk.toString()
|
|
33
|
+
})
|
|
34
|
+
child.stderr?.on('data', (chunk: Buffer) => {
|
|
35
|
+
output += chunk.toString()
|
|
36
|
+
})
|
|
37
|
+
child.on('close', (code) => {
|
|
38
|
+
resolve({ success: code === 0, output })
|
|
39
|
+
})
|
|
40
|
+
child.on('error', (err) => {
|
|
41
|
+
resolve({ success: false, output: `Error: ${err.message}` })
|
|
42
|
+
})
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export async function GET() {
|
|
47
|
+
return NextResponse.json(loadOntologyControlSummary())
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export async function POST(request: Request) {
|
|
51
|
+
const body = await request.json() as {
|
|
52
|
+
action?: 'refresh' | 'review' | 'deprecate'
|
|
53
|
+
conceptId?: string
|
|
54
|
+
decision?: 'promote' | 'reject' | 'defer'
|
|
55
|
+
rationale?: string
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (!body.action) {
|
|
59
|
+
return NextResponse.json({ success: false, error: 'action is required' }, { status: 400 })
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
let args: string[] = []
|
|
63
|
+
if (body.action === 'refresh') {
|
|
64
|
+
args = ['--refresh']
|
|
65
|
+
} else if (body.action === 'review') {
|
|
66
|
+
if (!body.conceptId || !body.decision) {
|
|
67
|
+
return NextResponse.json({ success: false, error: 'conceptId and decision are required for review' }, { status: 400 })
|
|
68
|
+
}
|
|
69
|
+
args = ['--review', body.conceptId, '--decision', body.decision]
|
|
70
|
+
if (body.rationale?.trim()) args.push('--rationale', body.rationale.trim())
|
|
71
|
+
} else if (body.action === 'deprecate') {
|
|
72
|
+
if (!body.conceptId) {
|
|
73
|
+
return NextResponse.json({ success: false, error: 'conceptId is required for deprecate' }, { status: 400 })
|
|
74
|
+
}
|
|
75
|
+
args = ['--deprecate', body.conceptId]
|
|
76
|
+
if (body.rationale?.trim()) args.push('--rationale', body.rationale.trim())
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const result = await runOntologyCommand(args)
|
|
80
|
+
if (!result.success) {
|
|
81
|
+
return NextResponse.json({ success: false, error: result.output || 'Ontology command failed' }, { status: 500 })
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return NextResponse.json({
|
|
85
|
+
success: true,
|
|
86
|
+
output: result.output,
|
|
87
|
+
dashboard: loadOntologyControlSummary(),
|
|
88
|
+
})
|
|
89
|
+
}
|
|
@@ -103,6 +103,14 @@ type Summary = {
|
|
|
103
103
|
|
|
104
104
|
interface Props {
|
|
105
105
|
summary: Summary
|
|
106
|
+
ontology: {
|
|
107
|
+
ontologyLoop: {
|
|
108
|
+
frontier: number
|
|
109
|
+
reviewOpen: number
|
|
110
|
+
extensions: number
|
|
111
|
+
changeEvents: number
|
|
112
|
+
}
|
|
113
|
+
}
|
|
106
114
|
}
|
|
107
115
|
|
|
108
116
|
function consoleTone(state: RunState): 'neutral' | 'green' | 'red' | 'yellow' {
|
|
@@ -145,7 +153,7 @@ function formatMode(mode: Summary['governance']['activeMode']) {
|
|
|
145
153
|
return mode.split('-').join(' ')
|
|
146
154
|
}
|
|
147
155
|
|
|
148
|
-
export default function CoEvolutionClient({ summary }: Props) {
|
|
156
|
+
export default function CoEvolutionClient({ summary, ontology }: Props) {
|
|
149
157
|
const [runState, setRunState] = useState<RunState>('idle')
|
|
150
158
|
const [activeCommand, setActiveCommand] = useState<CommandName | null>(null)
|
|
151
159
|
const [output, setOutput] = useState('')
|
|
@@ -246,6 +254,7 @@ export default function CoEvolutionClient({ summary }: Props) {
|
|
|
246
254
|
{ label: `${summary.pressureLifecycle.open} open`, tone: summary.pressureLifecycle.open > 0 ? 'yellow' : 'green' },
|
|
247
255
|
{ label: `${summary.pressureMotifs.promotionReady} promotion-ready motifs`, tone: summary.pressureMotifs.promotionReady > 0 ? 'purple' : 'neutral' },
|
|
248
256
|
{ label: `${summary.topologyReviews.open} topology reviews`, tone: summary.topologyReviews.open > 0 ? 'yellow' : 'green' },
|
|
257
|
+
{ label: `${ontology.ontologyLoop.frontier} ontology frontier`, tone: ontology.ontologyLoop.reviewOpen > 0 ? 'blue' : 'neutral' },
|
|
249
258
|
{ label: `${summary.recentTransfers.length} recent transfers`, tone: summary.recentTransfers.length > 0 ? 'green' : 'neutral' },
|
|
250
259
|
{ label: formatMode(summary.governance.activeMode), tone: toneForMode(summary.governance.activeMode) },
|
|
251
260
|
]}
|
|
@@ -264,6 +273,7 @@ export default function CoEvolutionClient({ summary }: Props) {
|
|
|
264
273
|
<button onClick={() => handleRun('research')} disabled={runState === 'running'} className="badge badge-blue" style={{ border: 'none', cursor: 'pointer' }}>Run research</button>
|
|
265
274
|
<button onClick={() => handleRun('evolve')} disabled={runState === 'running'} className="badge badge-green" style={{ border: 'none', cursor: 'pointer' }}>Run evolve</button>
|
|
266
275
|
<button onClick={() => handleRun('generalize')} disabled={runState === 'running'} className="badge badge-purple" style={{ border: 'none', cursor: 'pointer' }}>Run generalize</button>
|
|
276
|
+
<Link href="/ontology" className="badge badge-gray">Open ontology</Link>
|
|
267
277
|
<Link href="/topology" className="badge badge-gray">Open topology</Link>
|
|
268
278
|
</div>
|
|
269
279
|
</div>
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { loadCoEvolutionSummary } from '@/lib/data'
|
|
1
|
+
import { loadCoEvolutionSummary, loadOntologySummary } from '@/lib/data'
|
|
2
2
|
import CoEvolutionClient from './client'
|
|
3
3
|
|
|
4
4
|
export const dynamic = 'force-dynamic'
|
|
5
5
|
|
|
6
6
|
export default function CoEvolutionPage() {
|
|
7
7
|
const summary = loadCoEvolutionSummary()
|
|
8
|
-
|
|
8
|
+
const ontology = loadOntologySummary()
|
|
9
|
+
return <CoEvolutionClient summary={summary} ontology={ontology} />
|
|
9
10
|
}
|
|
@@ -131,6 +131,29 @@ const COMMANDS: CommandInfo[] = [
|
|
|
131
131
|
needsLLM: true,
|
|
132
132
|
runnable: { command: 'graph-rebuild', label: 'Rebuild Graph', icon: 'M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1', color: 'var(--purple)' },
|
|
133
133
|
},
|
|
134
|
+
{
|
|
135
|
+
name: 'ontology',
|
|
136
|
+
description: 'Govern the ontology frontier explicitly. Refresh provisional concepts from recurring evidence, review them with promote/reject/defer decisions, and deprecate approved extensions without allowing free-form semantic drift.',
|
|
137
|
+
usage: 'helixevo ontology [options]',
|
|
138
|
+
examples: [
|
|
139
|
+
{ cmd: 'helixevo ontology --status', desc: 'Show kernel, frontier, extension, and change-log counts' },
|
|
140
|
+
{ cmd: 'helixevo ontology --refresh', desc: 'Derive frontier concepts from recurring capability, pressure, and topology evidence' },
|
|
141
|
+
{ cmd: 'helixevo ontology --review ontology_capability_ui --decision promote', desc: 'Promote a frontier concept into approved ontology extensions' },
|
|
142
|
+
{ cmd: 'helixevo ontology --deprecate ontology_capability_ui', desc: 'Deprecate an approved ontology extension' },
|
|
143
|
+
],
|
|
144
|
+
options: [
|
|
145
|
+
{ flag: '--status', desc: 'Show ontology kernel, frontier, extension, and review state' },
|
|
146
|
+
{ flag: '--refresh', desc: 'Refresh frontier concepts from recurring evidence' },
|
|
147
|
+
{ flag: '--review <conceptId>', desc: 'Review a frontier concept' },
|
|
148
|
+
{ flag: '--decision <promote|reject|defer>', desc: 'Decision for --review' },
|
|
149
|
+
{ flag: '--rationale <text>', desc: 'Optional review or deprecate rationale' },
|
|
150
|
+
{ flag: '--deprecate <conceptId>', desc: 'Deprecate an approved ontology extension' },
|
|
151
|
+
{ flag: '--verbose', desc: 'Show detailed frontier concepts, extensions, and change events' },
|
|
152
|
+
],
|
|
153
|
+
category: 'network',
|
|
154
|
+
needsLLM: false,
|
|
155
|
+
note: 'Milestone 8 keeps ontology growth governed: concepts begin in the frontier, require explicit review, and only then become approved extensions.',
|
|
156
|
+
},
|
|
134
157
|
{
|
|
135
158
|
name: 'topology',
|
|
136
159
|
description: 'Move reviewed topology candidates through an explicit structural execution pipeline. Prepare accepted candidates, apply only the safe subset, inspect snapshots and artifacts, and roll back applied structural overrides when needed.',
|
|
@@ -467,6 +467,11 @@ helixevo topology --status`}</Code>
|
|
|
467
467
|
desc: 'Inspect the network and, with --optimize, refresh topology review candidates for structural issues and opportunities.',
|
|
468
468
|
flags: ['--mermaid', '--obsidian <vault>', '--rebuild', '--optimize', '--verbose'],
|
|
469
469
|
},
|
|
470
|
+
{
|
|
471
|
+
cmd: 'helixevo ontology',
|
|
472
|
+
desc: 'Govern the ontology frontier explicitly. Refresh concept hypotheses from recurring evidence, review them with promote/reject/defer decisions, and deprecate approved extensions without allowing free-form semantic drift.',
|
|
473
|
+
flags: ['--status', '--refresh', '--review <conceptId>', '--decision <promote|reject|defer>', '--rationale <text>', '--deprecate <conceptId>', '--verbose'],
|
|
474
|
+
},
|
|
470
475
|
{
|
|
471
476
|
cmd: 'helixevo topology',
|
|
472
477
|
desc: 'Move accepted topology review through prepare, apply, and rollback. This is the explicit control surface for reviewed structural execution.',
|
|
@@ -668,6 +673,7 @@ helixevo topology --status`}</Code>
|
|
|
668
673
|
['Overview', 'var(--blue)', 'Top-level cockpit for frontier state, brain foundation, pressure totals, topology review counts, and prepared/applied structural state.'],
|
|
669
674
|
['Co-Evolution', 'var(--purple)', 'The response cockpit. Use it to inspect routed pressure, governance mode, promotion queue, interventions, and transfer evidence.'],
|
|
670
675
|
['Skill Network', 'var(--green)', 'Graph-level understanding: relationships, co-evolution signals, inspector context, and structural handoff links.'],
|
|
676
|
+
['Ontology', 'var(--blue)', 'Semantic control surface for kernel visibility, frontier review, approved extensions, and ontology change events.'],
|
|
671
677
|
['Topology', 'var(--yellow)', 'Governed plasticity surface for review decisions, accepted-ready queue, prepared plans, apply, rollback, and execution history.'],
|
|
672
678
|
['Projects', 'var(--blue)', 'Project intake and project-aware pressure surface. Best for capability gaps, activation traces, and promotion feeders.'],
|
|
673
679
|
['Research', 'var(--purple)', 'Discovery-oriented view grounded in current pressure and routed recommendations rather than disconnected idea generation.'],
|
|
@@ -1080,6 +1086,12 @@ generation: 3
|
|
|
1080
1086
|
├── skill-graph.json # Cached network (nodes + edges + ontology version)
|
|
1081
1087
|
├── canary-registry.json # Active canary deployments
|
|
1082
1088
|
├── knowledge-buffer.json # Research discoveries + drafts
|
|
1089
|
+
├── ontology/
|
|
1090
|
+
│ ├── kernel.json # Materialized ontology kernel snapshot
|
|
1091
|
+
│ ├── extensions.json # Approved ontology extensions
|
|
1092
|
+
│ ├── frontier.json # Provisional frontier concepts awaiting review
|
|
1093
|
+
│ ├── reviews.jsonl # Ontology review decisions
|
|
1094
|
+
│ └── change-log.jsonl # Native ontology change events
|
|
1083
1095
|
├── general/ # Skills (SKILL.md files)
|
|
1084
1096
|
│ ├── my-skill/SKILL.md
|
|
1085
1097
|
│ └── ...
|
|
@@ -1091,6 +1103,7 @@ generation: 3
|
|
|
1091
1103
|
{[
|
|
1092
1104
|
['Observation memory', 'var(--blue)', 'failures.jsonl + activation-traces.jsonl capture what happened, where it happened, and which skills were active.'],
|
|
1093
1105
|
['Pressure & response memory', 'var(--yellow)', 'pressure-signals.jsonl + pressure-interventions.jsonl + transfer-events.jsonl describe demand, routing, and reusable promotion evidence.'],
|
|
1106
|
+
['Ontology frontier memory', 'var(--blue)', 'ontology/kernel.json + ontology/frontier.json + ontology/extensions.json + ontology/reviews.jsonl + ontology/change-log.jsonl preserve semantic kernel state, provisional concepts, approved extensions, and review/change lineage.'],
|
|
1094
1107
|
['Governance & review memory', 'var(--purple)', 'governance-state.json + topology-review-candidates.json + topology-review-decisions.jsonl preserve why structural decisions are being made.'],
|
|
1095
1108
|
['Topology execution memory', 'var(--green)', 'topology-overrides.json + topology-snapshots.json + topology-apply-plans.json + topology-executions.jsonl + topology-artifacts.jsonl preserve reviewed structural execution and rollback.'],
|
|
1096
1109
|
['Evaluation & frontier memory', 'var(--blue)', 'evolution-history.json + evolution-artifacts.jsonl + skill-tests.jsonl + canary-registry.json + frontier.json preserve proof, guardrails, and best configurations.'],
|
|
@@ -1171,7 +1184,8 @@ generation: 3
|
|
|
1171
1184
|
<ul className="guide-list" style={{ marginTop: 8 }}>
|
|
1172
1185
|
<li>full-spectrum autonomous destructive self-restructuring</li>
|
|
1173
1186
|
<li>broad automatic merge / split / prune application</li>
|
|
1174
|
-
<li>
|
|
1187
|
+
<li>broad automatic semantic remapping across historical data</li>
|
|
1188
|
+
<li>full kernel mutation or free-form ontology drift</li>
|
|
1175
1189
|
<li>complete autonomous structural governance without operator oversight</li>
|
|
1176
1190
|
</ul>
|
|
1177
1191
|
</div>
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import Link from 'next/link'
|
|
4
|
+
import { useState } from 'react'
|
|
5
|
+
import { ConsolePanel } from '@/components/console-panel'
|
|
6
|
+
import { MetricCard } from '@/components/metric-card'
|
|
7
|
+
import { PageHero } from '@/components/page-hero'
|
|
8
|
+
import { SectionFrame } from '@/components/section-frame'
|
|
9
|
+
import type { OntologyControlDashboardSummary, OntologyReviewDecisionStatus } from '@/lib/data'
|
|
10
|
+
|
|
11
|
+
type RunState = 'idle' | 'running' | 'success' | 'error'
|
|
12
|
+
|
|
13
|
+
function consoleTone(state: RunState): 'neutral' | 'green' | 'red' | 'yellow' {
|
|
14
|
+
if (state === 'success') return 'green'
|
|
15
|
+
if (state === 'error') return 'red'
|
|
16
|
+
return 'neutral'
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function toneForConcept(kind: string): 'blue' | 'green' | 'purple' | 'yellow' | 'neutral' {
|
|
20
|
+
if (kind === 'capability') return 'blue'
|
|
21
|
+
if (kind === 'pressure-type') return 'yellow'
|
|
22
|
+
if (kind === 'topology-motif') return 'purple'
|
|
23
|
+
return 'neutral'
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function formatDate(value: string | undefined) {
|
|
27
|
+
if (!value) return '—'
|
|
28
|
+
return new Date(value).toLocaleString()
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function formatMode(value: string) {
|
|
32
|
+
return value.replace(/-/g, ' ')
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export default function OntologyClient({ initialDashboard }: { initialDashboard: OntologyControlDashboardSummary }) {
|
|
36
|
+
const [dashboard, setDashboard] = useState(initialDashboard)
|
|
37
|
+
const [runState, setRunState] = useState<RunState>('idle')
|
|
38
|
+
const [output, setOutput] = useState('')
|
|
39
|
+
const [pendingKey, setPendingKey] = useState<string | null>(null)
|
|
40
|
+
|
|
41
|
+
const runAction = async (action: 'refresh' | 'review' | 'deprecate', payload: { conceptId?: string; decision?: OntologyReviewDecisionStatus; rationale?: string }, label: string) => {
|
|
42
|
+
setPendingKey(payload.conceptId ?? action)
|
|
43
|
+
setRunState('running')
|
|
44
|
+
setOutput('')
|
|
45
|
+
try {
|
|
46
|
+
const res = await fetch('/api/ontology', {
|
|
47
|
+
method: 'POST',
|
|
48
|
+
headers: { 'Content-Type': 'application/json' },
|
|
49
|
+
body: JSON.stringify({ action, ...payload }),
|
|
50
|
+
})
|
|
51
|
+
const data = await res.json()
|
|
52
|
+
if (!res.ok || !data.success) {
|
|
53
|
+
setRunState('error')
|
|
54
|
+
setOutput(data.error ?? `${label} failed`)
|
|
55
|
+
return
|
|
56
|
+
}
|
|
57
|
+
setDashboard(data.dashboard)
|
|
58
|
+
setRunState('success')
|
|
59
|
+
setOutput(data.output || `${label} completed`)
|
|
60
|
+
} catch (err: unknown) {
|
|
61
|
+
setRunState('error')
|
|
62
|
+
setOutput(err instanceof Error ? err.message : `${label} failed`)
|
|
63
|
+
} finally {
|
|
64
|
+
setPendingKey(null)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<div style={{ display: 'grid', gap: 22 }}>
|
|
70
|
+
<PageHero
|
|
71
|
+
eyebrow="Semantic plasticity"
|
|
72
|
+
title="Ontology Frontier Control"
|
|
73
|
+
description="Inspect the stable kernel, review frontier concept hypotheses derived from recurring evidence, promote durable concepts into approved extensions, and keep semantic plasticity governed rather than free-form."
|
|
74
|
+
chips={[
|
|
75
|
+
{ label: `${dashboard.summary.frontier} frontier`, tone: dashboard.summary.frontier > 0 ? 'yellow' : 'neutral' },
|
|
76
|
+
{ label: `${dashboard.summary.reviewOpen} open review`, tone: dashboard.summary.reviewOpen > 0 ? 'yellow' : 'green' },
|
|
77
|
+
{ label: `${dashboard.summary.extensions} approved extensions`, tone: dashboard.summary.extensions > 0 ? 'blue' : 'neutral' },
|
|
78
|
+
{ label: `${dashboard.summary.changeEvents} change events`, tone: dashboard.summary.changeEvents > 0 ? 'purple' : 'neutral' },
|
|
79
|
+
{ label: formatMode(dashboard.governance.activeMode), tone: dashboard.governance.activeMode === 'transfer-focused' ? 'purple' : dashboard.governance.activeMode === 'project-critical' ? 'yellow' : 'blue' },
|
|
80
|
+
]}
|
|
81
|
+
actions={
|
|
82
|
+
<div style={{ display: 'grid', gap: 12 }}>
|
|
83
|
+
<div className="hero-note-card">
|
|
84
|
+
<div className="hero-note-label">Native ontology state</div>
|
|
85
|
+
<div className="hero-note-title">Kernel + frontier + extensions</div>
|
|
86
|
+
<div className="hero-note-copy">Milestone 8 keeps the semantic kernel stable while letting new concepts emerge into a reviewable frontier before promotion.</div>
|
|
87
|
+
</div>
|
|
88
|
+
<div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', justifyContent: 'flex-end' }}>
|
|
89
|
+
<button onClick={() => runAction('refresh', {}, 'ontology refresh')} disabled={runState === 'running'} className="badge badge-blue" style={{ border: 'none', cursor: 'pointer' }}>Refresh ontology frontier</button>
|
|
90
|
+
<Link href="/coevolution" className="badge badge-gray">Open co-evolution</Link>
|
|
91
|
+
<Link href="/topology" className="badge badge-gray">Open topology</Link>
|
|
92
|
+
</div>
|
|
93
|
+
</div>
|
|
94
|
+
}
|
|
95
|
+
/>
|
|
96
|
+
|
|
97
|
+
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: 16 }}>
|
|
98
|
+
<MetricCard label="Kernel concepts" value={dashboard.summary.kernelConcepts} sublabel={`${dashboard.kernel.relationFamilies.length} relation families`} tone="purple" icon="◎" />
|
|
99
|
+
<MetricCard label="Frontier hypotheses" value={dashboard.summary.frontier} sublabel={`${dashboard.summary.reviewOpen} open • ${dashboard.summary.deferred} deferred`} tone={dashboard.summary.reviewOpen > 0 ? 'yellow' : 'neutral'} icon="◇" />
|
|
100
|
+
<MetricCard label="Approved extensions" value={dashboard.summary.extensions} sublabel={`${dashboard.summary.deprecated} deprecated`} tone={dashboard.summary.extensions > 0 ? 'blue' : 'neutral'} icon="↑" />
|
|
101
|
+
<MetricCard label="Concept changes" value={dashboard.summary.changeEvents} sublabel={`${dashboard.summary.promoted} promoted • ${dashboard.summary.rejected} rejected`} tone={dashboard.summary.changeEvents > 0 ? 'green' : 'neutral'} icon="⇄" />
|
|
102
|
+
</div>
|
|
103
|
+
|
|
104
|
+
<SectionFrame
|
|
105
|
+
eyebrow="Kernel"
|
|
106
|
+
title="Stable semantic anchor"
|
|
107
|
+
description="The kernel remains the constitutional layer. Milestone 8 does not mutate it directly; it materializes and exposes it while adding governed extension growth around it."
|
|
108
|
+
>
|
|
109
|
+
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
|
|
110
|
+
<span className="badge badge-gray">version {dashboard.kernel.version}</span>
|
|
111
|
+
<span className="badge badge-gray">{dashboard.kernel.entityNames.length} kernel entities</span>
|
|
112
|
+
<span className="badge badge-gray">{dashboard.kernel.mutationOperations.length} mutation operations</span>
|
|
113
|
+
<span className="badge badge-gray">{dashboard.kernel.invariantIds.length} invariants</span>
|
|
114
|
+
</div>
|
|
115
|
+
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))', gap: 12, marginTop: 16 }}>
|
|
116
|
+
<div className="guide-dimension-card" style={{ borderLeftColor: 'var(--blue)' }}>
|
|
117
|
+
<div style={{ fontSize: 12, fontWeight: 700, color: 'var(--blue)' }}>Kernel pillars</div>
|
|
118
|
+
<div style={{ fontSize: 12, color: 'var(--text-dim)', marginTop: 8, lineHeight: 1.6 }}>{dashboard.kernel.pillars.join(' • ')}</div>
|
|
119
|
+
</div>
|
|
120
|
+
<div className="guide-dimension-card" style={{ borderLeftColor: 'var(--green)' }}>
|
|
121
|
+
<div style={{ fontSize: 12, fontWeight: 700, color: 'var(--green)' }}>Allowed layers</div>
|
|
122
|
+
<div style={{ fontSize: 12, color: 'var(--text-dim)', marginTop: 8, lineHeight: 1.6 }}>{dashboard.kernel.layers.join(' • ')}</div>
|
|
123
|
+
</div>
|
|
124
|
+
</div>
|
|
125
|
+
</SectionFrame>
|
|
126
|
+
|
|
127
|
+
<SectionFrame
|
|
128
|
+
eyebrow="Frontier"
|
|
129
|
+
title="Reviewable concept hypotheses"
|
|
130
|
+
description="These concepts remain provisional until reviewed. Promotion materializes an approved extension; reject and defer preserve semantic memory without silent drift."
|
|
131
|
+
>
|
|
132
|
+
<div style={{ display: 'grid', gap: 12 }}>
|
|
133
|
+
{dashboard.frontier.length > 0 ? dashboard.frontier.map((concept) => (
|
|
134
|
+
<div key={concept.id} style={{ padding: '16px 18px', borderRadius: 18, border: '1px solid var(--border)', background: 'rgba(255,255,255,0.74)' }}>
|
|
135
|
+
<div style={{ display: 'flex', justifyContent: 'space-between', gap: 16, alignItems: 'flex-start', flexWrap: 'wrap' }}>
|
|
136
|
+
<div style={{ display: 'grid', gap: 4, flex: 1 }}>
|
|
137
|
+
<div style={{ fontSize: 13, fontWeight: 700, color: 'var(--text)' }}>{concept.name}</div>
|
|
138
|
+
<div style={{ fontSize: 12, color: 'var(--text-dim)', lineHeight: 1.6 }}>{concept.description ?? concept.sourceSummary ?? 'Provisional ontology hypothesis.'}</div>
|
|
139
|
+
</div>
|
|
140
|
+
<div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
|
|
141
|
+
<span className={`badge badge-${toneForConcept(concept.conceptKind)}`}>{concept.conceptKind}</span>
|
|
142
|
+
<span className="badge badge-gray">{concept.reviewStatus}</span>
|
|
143
|
+
<span className="badge badge-gray">{concept.observationCount ?? 0} obs</span>
|
|
144
|
+
<span className="badge badge-gray">{((concept.confidence ?? 0) * 100).toFixed(0)}% confidence</span>
|
|
145
|
+
</div>
|
|
146
|
+
</div>
|
|
147
|
+
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginTop: 12 }}>
|
|
148
|
+
<span className="badge badge-gray">{(concept.projectIds?.length ?? 0)} projects</span>
|
|
149
|
+
<span className="badge badge-gray">{(concept.evidenceIds?.length ?? 0)} evidence ids</span>
|
|
150
|
+
<span className="badge badge-gray">last seen {formatDate(concept.lastObservedAt)}</span>
|
|
151
|
+
</div>
|
|
152
|
+
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginTop: 14 }}>
|
|
153
|
+
<button onClick={() => runAction('review', { conceptId: concept.id, decision: 'promote', rationale: `Promote ${concept.name} into approved ontology extension.` }, `promote ${concept.name}`)} disabled={pendingKey === concept.id} className="badge badge-blue" style={{ border: 'none', cursor: 'pointer' }}>Promote</button>
|
|
154
|
+
<button onClick={() => runAction('review', { conceptId: concept.id, decision: 'defer', rationale: `Defer ${concept.name} for more evidence.` }, `defer ${concept.name}`)} disabled={pendingKey === concept.id} className="badge badge-purple" style={{ border: 'none', cursor: 'pointer' }}>Defer</button>
|
|
155
|
+
<button onClick={() => runAction('review', { conceptId: concept.id, decision: 'reject', rationale: `Reject ${concept.name} as a weak or overlapping frontier concept.` }, `reject ${concept.name}`)} disabled={pendingKey === concept.id} className="badge badge-gray" style={{ border: 'none', cursor: 'pointer' }}>Reject</button>
|
|
156
|
+
</div>
|
|
157
|
+
</div>
|
|
158
|
+
)) : (
|
|
159
|
+
<div className="empty-state" style={{ padding: 24 }}>
|
|
160
|
+
<div className="empty-state-title">No ontology frontier concepts yet</div>
|
|
161
|
+
<div className="empty-state-desc">Run “Refresh ontology frontier” after pressure motifs, project gaps, or topology review patterns accumulate.</div>
|
|
162
|
+
</div>
|
|
163
|
+
)}
|
|
164
|
+
</div>
|
|
165
|
+
</SectionFrame>
|
|
166
|
+
|
|
167
|
+
<SectionFrame
|
|
168
|
+
eyebrow="Extensions"
|
|
169
|
+
title="Approved ontology extensions"
|
|
170
|
+
description="Promoted concepts live here as approved semantic vocabulary. Deprecation is bounded and explicit — there is no hidden semantic drift."
|
|
171
|
+
>
|
|
172
|
+
<div style={{ display: 'grid', gap: 12 }}>
|
|
173
|
+
{dashboard.extensions.length > 0 ? dashboard.extensions.map((concept) => (
|
|
174
|
+
<div key={concept.id} style={{ padding: '16px 18px', borderRadius: 18, border: '1px solid var(--border)', background: 'rgba(255,255,255,0.74)' }}>
|
|
175
|
+
<div style={{ display: 'flex', justifyContent: 'space-between', gap: 16, alignItems: 'flex-start', flexWrap: 'wrap' }}>
|
|
176
|
+
<div style={{ display: 'grid', gap: 4, flex: 1 }}>
|
|
177
|
+
<div style={{ fontSize: 13, fontWeight: 700, color: 'var(--text)' }}>{concept.name}</div>
|
|
178
|
+
<div style={{ fontSize: 12, color: 'var(--text-dim)', lineHeight: 1.6 }}>{concept.description ?? concept.sourceSummary ?? 'Approved ontology extension.'}</div>
|
|
179
|
+
</div>
|
|
180
|
+
<div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
|
|
181
|
+
<span className={`badge badge-${toneForConcept(concept.conceptKind)}`}>{concept.conceptKind}</span>
|
|
182
|
+
<span className="badge badge-gray">{concept.status}</span>
|
|
183
|
+
<span className="badge badge-gray">{(concept.evidenceIds?.length ?? 0)} evidence ids</span>
|
|
184
|
+
</div>
|
|
185
|
+
</div>
|
|
186
|
+
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginTop: 12 }}>
|
|
187
|
+
<span className="badge badge-gray">{(concept.projectIds?.length ?? 0)} projects</span>
|
|
188
|
+
<span className="badge badge-gray">created {formatDate(concept.createdAt)}</span>
|
|
189
|
+
{concept.status !== 'deprecated' ? (
|
|
190
|
+
<button onClick={() => runAction('deprecate', { conceptId: concept.id, rationale: `Deprecate ontology extension ${concept.name} after operator review.` }, `deprecate ${concept.name}`)} disabled={pendingKey === concept.id} className="badge badge-gray" style={{ border: 'none', cursor: 'pointer' }}>Deprecate</button>
|
|
191
|
+
) : null}
|
|
192
|
+
</div>
|
|
193
|
+
</div>
|
|
194
|
+
)) : (
|
|
195
|
+
<div className="empty-state" style={{ padding: 24 }}>
|
|
196
|
+
<div className="empty-state-title">No approved extensions yet</div>
|
|
197
|
+
<div className="empty-state-desc">Promoted frontier concepts will appear here once they pass semantic review.</div>
|
|
198
|
+
</div>
|
|
199
|
+
)}
|
|
200
|
+
</div>
|
|
201
|
+
</SectionFrame>
|
|
202
|
+
|
|
203
|
+
<SectionFrame
|
|
204
|
+
eyebrow="Change log"
|
|
205
|
+
title="Recent semantic transitions"
|
|
206
|
+
description="Every meaningful ontology action should leave behind a visible change trail instead of becoming invisible semantic drift."
|
|
207
|
+
>
|
|
208
|
+
<div style={{ display: 'grid', gap: 10 }}>
|
|
209
|
+
{dashboard.recentChanges.length > 0 ? dashboard.recentChanges.map((event) => (
|
|
210
|
+
<div key={event.id} style={{ padding: '14px 16px', borderRadius: 18, border: '1px solid var(--border)', background: 'rgba(255,255,255,0.72)' }}>
|
|
211
|
+
<div style={{ display: 'flex', justifyContent: 'space-between', gap: 16, flexWrap: 'wrap' }}>
|
|
212
|
+
<div style={{ fontSize: 12.5, fontWeight: 700, color: 'var(--text)' }}>{event.changeType}</div>
|
|
213
|
+
<span className="badge badge-gray">{formatDate(event.timestamp)}</span>
|
|
214
|
+
</div>
|
|
215
|
+
<div style={{ fontSize: 12, color: 'var(--text-dim)', marginTop: 6, lineHeight: 1.6 }}>{event.reason}</div>
|
|
216
|
+
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginTop: 10 }}>
|
|
217
|
+
<span className="badge badge-gray">{event.conceptIds.join(', ')}</span>
|
|
218
|
+
<span className="badge badge-gray">{(event.evidenceIds?.length ?? 0)} evidence ids</span>
|
|
219
|
+
</div>
|
|
220
|
+
</div>
|
|
221
|
+
)) : (
|
|
222
|
+
<div className="empty-state" style={{ padding: 24 }}>
|
|
223
|
+
<div className="empty-state-title">No ontology changes logged yet</div>
|
|
224
|
+
<div className="empty-state-desc">Refresh the frontier or review a concept to create the first native ontology events.</div>
|
|
225
|
+
</div>
|
|
226
|
+
)}
|
|
227
|
+
</div>
|
|
228
|
+
</SectionFrame>
|
|
229
|
+
|
|
230
|
+
<ConsolePanel
|
|
231
|
+
title="Ontology console"
|
|
232
|
+
tone={consoleTone(runState)}
|
|
233
|
+
actions={<span className="badge badge-gray">{runState === 'running' ? 'running' : runState === 'success' ? 'success' : runState === 'error' ? 'error' : 'idle'}</span>}
|
|
234
|
+
>
|
|
235
|
+
<pre style={{ margin: 0, whiteSpace: 'pre-wrap', fontSize: 12, lineHeight: 1.7, color: 'var(--text-dim)' }}>
|
|
236
|
+
{runState === 'running'
|
|
237
|
+
? 'Running ontology control…\n\n' + (output || '')
|
|
238
|
+
: runState === 'success'
|
|
239
|
+
? (output || 'Ontology action completed.')
|
|
240
|
+
: runState === 'error'
|
|
241
|
+
? (output || 'Ontology action failed.')
|
|
242
|
+
: 'Refresh the frontier or review concepts to inspect semantic changes.'}
|
|
243
|
+
</pre>
|
|
244
|
+
</ConsolePanel>
|
|
245
|
+
</div>
|
|
246
|
+
)
|
|
247
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import OntologyClient from './client'
|
|
2
|
+
import { loadOntologyControlSummary } from '@/lib/data'
|
|
3
|
+
|
|
4
|
+
export const dynamic = 'force-dynamic'
|
|
5
|
+
|
|
6
|
+
export default function OntologyPage() {
|
|
7
|
+
const dashboard = loadOntologyControlSummary()
|
|
8
|
+
return <OntologyClient initialDashboard={dashboard} />
|
|
9
|
+
}
|
package/dashboard/app/page.tsx
CHANGED
|
@@ -83,8 +83,8 @@ export default function Overview() {
|
|
|
83
83
|
<SectionFrame
|
|
84
84
|
eyebrow="Brain foundation"
|
|
85
85
|
title="Semantic backbone"
|
|
86
|
-
description="A
|
|
87
|
-
actions={<span className="badge badge-gray">{ontology.source === 'graph' ? `Ontology ${ontology.specVersion}` : 'Compatibility-derived'}</span>}
|
|
86
|
+
description="A hybrid ontology view of the living brain, combining derived skill-graph semantics with native ontology frontier, extension, and semantic review activity."
|
|
87
|
+
actions={<span className="badge badge-gray">{ontology.source === 'hybrid-native-derived' ? `Ontology ${ontology.specVersion} · hybrid native + derived` : ontology.source === 'graph' ? `Ontology ${ontology.specVersion}` : 'Compatibility-derived'}</span>}
|
|
88
88
|
>
|
|
89
89
|
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: 16 }}>
|
|
90
90
|
<MetricCard
|
|
@@ -143,6 +143,14 @@ export default function Overview() {
|
|
|
143
143
|
href="/topology"
|
|
144
144
|
icon="⇄"
|
|
145
145
|
/>
|
|
146
|
+
<MetricCard
|
|
147
|
+
label="Ontology frontier"
|
|
148
|
+
value={ontology.ontologyLoop.frontier}
|
|
149
|
+
sublabel={`${ontology.ontologyLoop.reviewOpen} open • ${ontology.ontologyLoop.extensions} approved extensions`}
|
|
150
|
+
tone={ontology.ontologyLoop.reviewOpen > 0 ? 'yellow' : ontology.ontologyLoop.extensions > 0 ? 'blue' : 'neutral'}
|
|
151
|
+
href="/ontology"
|
|
152
|
+
icon="◎"
|
|
153
|
+
/>
|
|
146
154
|
<MetricCard
|
|
147
155
|
label="Observed mutation verbs"
|
|
148
156
|
value={ontology.mutationOperationsObserved}
|
|
@@ -166,8 +174,10 @@ export default function Overview() {
|
|
|
166
174
|
<span className="badge badge-gray">{coevolution.crossProjectGapAreas.length} cross-project gap motifs</span>
|
|
167
175
|
<span className="badge badge-gray">{ontology.pressureMotifs.promotionReady} motifs currently recommend generalize</span>
|
|
168
176
|
<span className="badge badge-gray">{ontology.transferEvents.total} transfer events logged ({ontology.transferEvents.realized} realized)</span>
|
|
177
|
+
<span className="badge badge-gray">ontology → {ontology.ontologyLoop.frontier} frontier • {ontology.ontologyLoop.extensions} extensions • {ontology.ontologyLoop.changeEvents} changes</span>
|
|
169
178
|
<span className="badge badge-gray">topology → {ontology.topologyReviews.open} open • {ontology.topologyReviews.accepted} accepted • {ontology.topologyReviews.generatedFromManualReview} manual-route</span>
|
|
170
179
|
<span className="badge badge-gray">execution → {ontology.topologyExecution.prepared} prepared • {ontology.topologyExecution.applied} applied • {ontology.topologyExecution.rolledBack} rolled back</span>
|
|
180
|
+
<Link href="/ontology" className="badge badge-blue" style={{ textDecoration: 'none' }}>Open ontology control</Link>
|
|
171
181
|
<Link href="/topology" className="badge badge-blue" style={{ textDecoration: 'none' }}>Open topology control</Link>
|
|
172
182
|
<span className="badge badge-gray">governance: {ontology.governance.activeMode.replace(/-/g, ' ')} ({ontology.governance.source})</span>
|
|
173
183
|
<span className="badge badge-gray">routes → research {ontology.governedRoutes.research} • specialize {ontology.governedRoutes.specialize} • evolve {ontology.governedRoutes.evolve} • generalize {ontology.governedRoutes.generalize} • manual-review {ontology.governedRoutes['manual-review']}</span>
|
|
@@ -253,6 +253,7 @@ export default function TopologyClient({
|
|
|
253
253
|
</div>
|
|
254
254
|
<div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', justifyContent: 'flex-end' }}>
|
|
255
255
|
<button onClick={handleOptimize} disabled={runState === 'running'} className="badge badge-blue" style={{ border: 'none', cursor: 'pointer' }}>Run graph optimize</button>
|
|
256
|
+
<Link href="/ontology" className="badge badge-gray">Open ontology</Link>
|
|
256
257
|
<Link href="/coevolution" className="badge badge-gray">Open co-evolution</Link>
|
|
257
258
|
<Link href="/network" className="badge badge-gray">Open network</Link>
|
|
258
259
|
</div>
|
|
@@ -12,6 +12,7 @@ interface NavItem {
|
|
|
12
12
|
const WORKSPACE_NAV: NavItem[] = [
|
|
13
13
|
{ href: '/', label: 'Overview', icon: 'M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-4 0a1 1 0 01-1-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 01-1 1' },
|
|
14
14
|
{ href: '/network', label: 'Skill Network', icon: 'M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1' },
|
|
15
|
+
{ href: '/ontology', label: 'Ontology', icon: 'M12 3l8 4.5v9L12 21l-8-4.5v-9L12 3zm0 4.2l-4 2.25v4.95l4 2.25 4-2.25V9.45L12 7.2zm0 0V21' },
|
|
15
16
|
{ href: '/topology', label: 'Topology', icon: 'M4 7h6m4 0h6M7 4v6m10-6v6M5 17h14M12 10v10' },
|
|
16
17
|
{ href: '/coevolution', label: 'Co-Evolution', icon: 'M4 12h4m8 0h4M12 4v4m0 8v4M7.05 7.05l2.83 2.83m4.24 4.24l2.83 2.83m0-9.9l-2.83 2.83m-4.24 4.24l-2.83 2.83' },
|
|
17
18
|
{ href: '/evolution', label: 'Evolution', icon: 'M13 7h8m0 0v8m0-8l-8 8-4-4-6 6' },
|