Decompose monolithic architecture.md into modular docs/architecture/ documents
The 751-line architecture.md violated the SDD process modular documentation target (~500 lines). It also had duplicate TaskGraph class definitions (one monolith, one decomposed) that directly contradicted each other, and embedded consumer-specific tool dispatch mappings that belong in downstream projects. Changes: - Split into 8 focused documents + 7 ADR records + redirect page - Removed the monolithic TaskGraph class (kept only decomposed version) - Moved CLI→plugin dispatch mapping out (belongs in plugin architecture) - Extracted implementation code (frontmatter splitter, findCycles, DAG propagation) into WHAT/WHY descriptions per architect role spec - Added proper ADR format for all resolved design decisions - Fixed review issues: C_fail mapping, DuplicateNodeError/DuplicateEdgeError types, ValidationError/GraphValidationError definitions, mutation error handling contract, enum naming convention, validation timing clarification
This commit is contained in:
89
docs/architecture/build-distribution.md
Normal file
89
docs/architecture/build-distribution.md
Normal file
@@ -0,0 +1,89 @@
|
||||
---
|
||||
status: draft
|
||||
last_updated: 2026-04-26
|
||||
---
|
||||
|
||||
# Build & Distribution
|
||||
|
||||
Dependencies, project structure, build targets, and performance notes.
|
||||
|
||||
## Dependencies
|
||||
|
||||
| Package | Purpose |
|
||||
|---------|---------|
|
||||
| `graphology` | Directed graph data structure + event emitter |
|
||||
| `graphology-dag` | hasCycle, topologicalSort, topologicalGenerations |
|
||||
| `graphology-metrics` | betweenness centrality (bottleneck) |
|
||||
| `graphology-components` | strongly-connected components (findCycles pre-check) |
|
||||
| `graphology-operators` | subgraph extraction |
|
||||
| `@alkdev/typebox` | Schema definition, static types, runtime validation |
|
||||
| `yaml` | YAML 1.2 parser (zero dependencies, no known CVEs) |
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
taskgraph_ts/
|
||||
├── package.json
|
||||
├── tsconfig.json
|
||||
├── src/
|
||||
│ ├── index.ts # Public API surface, re-exports
|
||||
│ ├── schema/
|
||||
│ │ ├── index.ts # Re-exports all schemas
|
||||
│ │ ├── enums.ts # TaskScope, TaskRisk, TaskImpact, TaskLevel, TaskStatus, TaskPriority
|
||||
│ │ ├── task.ts # TaskInput, DependencyEdge schemas
|
||||
│ │ ├── graph.ts # TaskGraphNodeAttributes, TaskGraphEdgeAttributes, SerializedGraph
|
||||
│ │ └── results.ts # RiskPathResult, DecomposeResult, WorkflowCostResult, RiskDistributionResult
|
||||
│ ├── graph/
|
||||
│ │ ├── index.ts # TaskGraph class
|
||||
│ │ ├── construction.ts # fromTasks, fromRecords, fromJSON, incremental building
|
||||
│ │ ├── queries.ts # hasCycles, findCycles, topologicalOrder, dependencies, dependents
|
||||
│ │ └── mutation.ts # removeTask, removeDependency, updateTask, updateEdgeAttributes
|
||||
│ ├── analysis/
|
||||
│ │ ├── index.ts # Re-exports
|
||||
│ │ ├── critical-path.ts # criticalPath, weightedCriticalPath
|
||||
│ │ ├── bottleneck.ts # bottlenecks (graphology betweenness)
|
||||
│ │ ├── risk.ts # riskPath, riskDistribution
|
||||
│ │ ├── cost-benefit.ts # calculateTaskEv, workflowCost, computeEffectiveP
|
||||
│ │ ├── decompose.ts # shouldDecomposeTask
|
||||
│ │ └── defaults.ts # resolveDefaults, enum numeric methods
|
||||
│ ├── frontmatter/
|
||||
│ │ ├── index.ts # parseFrontmatter, parseTaskFile, parseTaskDirectory, serializeFrontmatter
|
||||
│ │ ├── parse.ts # YAML/frontmatter parsing + typebox validation
|
||||
│ │ └── serialize.ts # TaskInput → markdown with frontmatter
|
||||
│ └── error/
|
||||
│ └── index.ts # TaskgraphError, TaskNotFoundError, CircularDependencyError, InvalidInputError
|
||||
├── test/
|
||||
│ ├── graph.test.ts
|
||||
│ ├── analysis.test.ts
|
||||
│ ├── schema.test.ts
|
||||
│ ├── frontmatter.test.ts
|
||||
│ └── cost-benefit.test.ts
|
||||
└── docs/
|
||||
└── architecture/ # This architecture document set
|
||||
```
|
||||
|
||||
The structure reflects the decomposition decision: `src/analysis/` contains standalone functions, `src/graph/` contains the TaskGraph data class. This is not an accident — it enforces at the filesystem level that analysis functions are separate from the graph class.
|
||||
|
||||
## Build & Distribution
|
||||
|
||||
- **Package**: `@alkdev/taskgraph` on npm
|
||||
- **Module**: ESM primary, CJS compat
|
||||
- **Targets**: Node 18+, Deno, Bun — pure JS, no native addons
|
||||
- **Build**: `tsc` for declarations + bundler for distribution
|
||||
- **No platform-specific binaries** — this is the whole point of the pivot from NAPI/Rust
|
||||
|
||||
## Performance Notes
|
||||
|
||||
From graphology's performance tips:
|
||||
- Prefer callback iteration (`forEachNode`, `forEachEdge`) over array-returning methods (`nodes()`, `edges()`) when iterating
|
||||
- Use `addEdgeWithKey` with deterministic `${source}->${target}` keys instead of `addEdge` to skip the automatic key generation overhead — see [ADR-006](decisions/006-deterministic-edge-keys.md)
|
||||
- Avoid callback nesting in hot loops; hoist inner callbacks
|
||||
- For bulk construction, `graph.import(serializedData)` is faster than N individual add calls
|
||||
|
||||
Realistic task graphs (10–200 nodes) make all of this academic, but the patterns are free to adopt.
|
||||
|
||||
## Constraints
|
||||
|
||||
- **Pure JavaScript** — no Rust, no WASM, no native addons. This is non-negotiable — it's the core design decision.
|
||||
- **ESM primary** — CJS compat is a distribution concern, not a design choice. Consumers should import as ESM.
|
||||
- **No platform-specific binaries** — the library must work in Node, Deno, and Bun without compilation steps.
|
||||
Reference in New Issue
Block a user