refactor: order module-graph table topologically (low→high level)
Replace the alphabetical package ordering with a Kahn-style topological sort (alphabetical tiebreak within each layer to stay deterministic), so the table and graph list leaf interfaces first and dependents last.
This commit is contained in:
+16
-16
@@ -9,41 +9,41 @@ package `a` depends on package `b`. Names have the `@deepseek-ai/dsh-` prefix st
|
|||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
graph TD
|
graph TD
|
||||||
|
bash-local --> bash
|
||||||
|
llm-deepseek --> llm
|
||||||
|
llm-pi-ai --> llm
|
||||||
|
session --> llm
|
||||||
|
system-prompt --> llm
|
||||||
agent --> llm
|
agent --> llm
|
||||||
agent --> session
|
agent --> session
|
||||||
|
invariants --> agent
|
||||||
|
invariants --> llm
|
||||||
|
invariants --> session
|
||||||
|
tools --> agent
|
||||||
|
tools --> llm
|
||||||
|
tools --> system-prompt
|
||||||
agent-loop --> agent
|
agent-loop --> agent
|
||||||
agent-loop --> llm
|
agent-loop --> llm
|
||||||
agent-loop --> session
|
agent-loop --> session
|
||||||
agent-loop --> system-prompt
|
agent-loop --> system-prompt
|
||||||
agent-loop --> tools
|
agent-loop --> tools
|
||||||
bash-local --> bash
|
|
||||||
invariants --> agent
|
|
||||||
invariants --> llm
|
|
||||||
invariants --> session
|
|
||||||
llm-deepseek --> llm
|
|
||||||
llm-pi-ai --> llm
|
|
||||||
session --> llm
|
|
||||||
system-prompt --> llm
|
|
||||||
tool-bash --> agent
|
tool-bash --> agent
|
||||||
tool-bash --> bash
|
tool-bash --> bash
|
||||||
tool-bash --> llm
|
tool-bash --> llm
|
||||||
tool-bash --> tools
|
tool-bash --> tools
|
||||||
tools --> agent
|
|
||||||
tools --> llm
|
|
||||||
tools --> system-prompt
|
|
||||||
```
|
```
|
||||||
|
|
||||||
| Package | Depends on |
|
| Package | Depends on |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `agent` | `llm`, `session` |
|
|
||||||
| `agent-loop` | `agent`, `llm`, `session`, `system-prompt`, `tools` |
|
|
||||||
| `bash` | — |
|
| `bash` | — |
|
||||||
| `bash-local` | `bash` |
|
|
||||||
| `invariants` | `agent`, `llm`, `session` |
|
|
||||||
| `llm` | — |
|
| `llm` | — |
|
||||||
|
| `bash-local` | `bash` |
|
||||||
| `llm-deepseek` | `llm` |
|
| `llm-deepseek` | `llm` |
|
||||||
| `llm-pi-ai` | `llm` |
|
| `llm-pi-ai` | `llm` |
|
||||||
| `session` | `llm` |
|
| `session` | `llm` |
|
||||||
| `system-prompt` | `llm` |
|
| `system-prompt` | `llm` |
|
||||||
| `tool-bash` | `agent`, `bash`, `llm`, `tools` |
|
| `agent` | `llm`, `session` |
|
||||||
|
| `invariants` | `agent`, `llm`, `session` |
|
||||||
| `tools` | `agent`, `llm`, `system-prompt` |
|
| `tools` | `agent`, `llm`, `system-prompt` |
|
||||||
|
| `agent-loop` | `agent`, `llm`, `session`, `system-prompt`, `tools` |
|
||||||
|
| `tool-bash` | `agent`, `bash`, `llm`, `tools` |
|
||||||
|
|||||||
@@ -46,7 +46,32 @@ function collect(): Pkg[] {
|
|||||||
.sort()
|
.sort()
|
||||||
pkgs.push({ short: json.name.slice(SCOPE.length), deps })
|
pkgs.push({ short: json.name.slice(SCOPE.length), deps })
|
||||||
}
|
}
|
||||||
return pkgs.sort((a, b) => a.short.localeCompare(b.short))
|
return topoSort(pkgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Order packages low-level → high-level: a package appears only after every
|
||||||
|
* package it depends on. Kahn-style layering with an alphabetical tiebreak
|
||||||
|
* within each layer, so the output stays deterministic (the freshness check
|
||||||
|
* compares whole-file). The graph is a DAG, so this always terminates; a cycle
|
||||||
|
* would leave nodes unplaced and throw.
|
||||||
|
*/
|
||||||
|
function topoSort(pkgs: Pkg[]): Pkg[] {
|
||||||
|
const remaining = new Map(pkgs.map(p => [p.short, p]))
|
||||||
|
const placed = new Set<string>()
|
||||||
|
const out: Pkg[] = []
|
||||||
|
while (remaining.size > 0) {
|
||||||
|
const ready = [...remaining.values()]
|
||||||
|
.filter(p => p.deps.every(d => placed.has(d)))
|
||||||
|
.sort((a, b) => a.short.localeCompare(b.short))
|
||||||
|
if (ready.length === 0) throw new Error(`gen-module-graph: dependency cycle among ${[...remaining.keys()].join(', ')}`)
|
||||||
|
for (const p of ready) {
|
||||||
|
out.push(p)
|
||||||
|
placed.add(p.short)
|
||||||
|
remaining.delete(p.short)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Render the full docs/module-graph.md content (pure, deterministic). */
|
/** Render the full docs/module-graph.md content (pure, deterministic). */
|
||||||
|
|||||||
Reference in New Issue
Block a user