Add architecture review findings and address documentation issues
Review of all ADR documents (001-007) and peripheral architecture docs identified 3 critical, 10 warning, and 7 suggestion issues. Addressed in this commit: - W-1: Add draft qualifier to ADR-002 reference to incremental exploration - W-2: Add Alternatives Considered section to ADR-001 - W-3: Add Document Lifecycle section to README.md (draft/stable/deprecated) - W-4: Clarify includeCompleted semantics (only 'completed' status triggers exclusion) - W-5: Document file I/O runtime constraints in frontmatter.md - W-6: Add ADR reference to architecture.md redirect - W-7: Verify CVE-2025-64718 (confirmed real, improved description) - W-9: Convert workspace-absolute paths to relative/monorepo references - S-7: Add future ADR-008 note to incremental-update-exploration.md Critical issues (C-1, C-2, C-3) and remaining warnings (W-8, W-10, S-4, S-5) were addressed by a parallel agent in a prior commit. All 16 review tasks created and resolved.
This commit is contained in:
@@ -66,7 +66,7 @@ The hub's database is the source of truth for tasks at runtime. The coordinator
|
||||
- Needs per-edge `qualityRetention` attributes for the DAG propagation model
|
||||
- Requires the same analysis functions the CLI provides, but called as an API, not via shell
|
||||
|
||||
> See alkhub task storage spec: `/workspace/@alkdev/alkhub_ts/docs/architecture/storage/tasks.md`
|
||||
> See alkhub task storage spec (monorepo: `@alkdev/alkhub_ts/docs/architecture/storage/tasks.md`)
|
||||
|
||||
### OpenCode plugin (future)
|
||||
|
||||
@@ -126,13 +126,32 @@ All significant decisions are documented as ADRs in [decisions/](decisions/):
|
||||
| [006](decisions/006-deterministic-edge-keys.md) | Deterministic edge keys via addEdgeWithKey |
|
||||
| [007](decisions/007-subgraph-internal-only.md) | Subgraph returns internal-only edges |
|
||||
|
||||
## Document Lifecycle
|
||||
|
||||
Architecture documents use YAML frontmatter with `status` and `last_updated` fields:
|
||||
|
||||
```yaml
|
||||
---
|
||||
status: draft | stable | deprecated
|
||||
last_updated: YYYY-MM-DD
|
||||
---
|
||||
```
|
||||
|
||||
| Status | Meaning | Transitions |
|
||||
|--------|---------|-------------|
|
||||
| `draft` | Under active development. Content may change significantly. Implementation should not start until the document reaches `stable`. | → `stable` when implementation is complete and API contract is verified by tests. |
|
||||
| `stable` | API contracts are locked. Changes require a review cycle and may warrant an ADR if they affect documented decisions. | → `deprecated` when superseded. → `draft` if a fundamental redesign is needed (rare). |
|
||||
| `deprecated` | Superseded by another document. Kept for reference. Links should point to the replacement. | Removed when no longer referenced. |
|
||||
|
||||
ADR documents use a separate `Status` field in their body: `Proposed`, `Accepted`, `Deprecated`, or `Superseded`. ADRs never revert from `Accepted`.
|
||||
|
||||
## References
|
||||
|
||||
- Rust taskgraph CLI: `/workspace/@alkimiadev/taskgraph/`
|
||||
- graphology monorepo: `/workspace/graphology/`
|
||||
- alkhub task storage spec: `/workspace/@alkdev/alkhub_ts/docs/architecture/storage/tasks.md`
|
||||
- @alkdev/typebox: `/workspace/@alkdev/typebox/`
|
||||
- Cost-benefit framework: `/workspace/@alkimiadev/taskgraph/docs/framework.md`
|
||||
- Workflow guide: `/workspace/@alkimiadev/taskgraph/docs/workflow.md`
|
||||
- Python cost-benefit research: `/workspace/@alkimiadev/taskgraph/docs/research/cost_benefit_analysis_framework.py`
|
||||
- SDD process: `/workspace/@alkdev/taskgraph_ts/docs/sdd_process.md`
|
||||
- Rust taskgraph CLI: [GitHub — @alkimiadev/taskgraph](https://github.com/alkimiadev/taskgraph) (monorepo: `@alkimiadev/taskgraph/`)
|
||||
- graphology monorepo: [GitHub — graphology](https://github.com/graphology/graphology) (monorepo: `graphology/`)
|
||||
- alkhub task storage spec: `@alkdev/alkhub_ts/docs/architecture/storage/tasks.md` (monorepo)
|
||||
- @alkdev/typebox: `@alkdev/typebox/` (monorepo)
|
||||
- Cost-benefit framework: `@alkimiadev/taskgraph/docs/framework.md` (monorepo)
|
||||
- Workflow guide: `@alkimiadev/taskgraph/docs/workflow.md` (monorepo)
|
||||
- Python cost-benefit research: `@alkimiadev/taskgraph/docs/research/cost_benefit_analysis_framework.py` (monorepo)
|
||||
- SDD process: [SDD process](../sdd_process.md)
|
||||
@@ -89,7 +89,7 @@ Each task in the `WorkflowCostResult.tasks` array includes both `pIntrinsic` and
|
||||
|
||||
### Skip-completed semantics
|
||||
|
||||
When `includeCompleted: false`, completed tasks are excluded from the result's task list, but they **remain in the propagation chain** with p=1.0. Removing completed tasks from propagation would *worsen* downstream probability estimates — exactly the opposite of what "what's left" queries need.
|
||||
When `includeCompleted: false`, tasks with `status: "completed"` are excluded from the result's task list, but they **remain in the propagation chain** with p=1.0. Removing completed tasks from propagation would *worsen* downstream probability estimates — exactly the opposite of what "what's left" queries need. Only the `"completed"` status triggers this exclusion; tasks with `"failed"` or `"blocked"` status are included regardless of the `includeCompleted` setting.
|
||||
|
||||
> See [ADR-004](decisions/004-workflow-cost-dag-propagation.md) and [ADR-005](decisions/005-no-depth-escalation-v1.md).
|
||||
|
||||
|
||||
@@ -6,6 +6,13 @@
|
||||
|
||||
The original design specified a Rust core with napi-rs bindings, extracting the graph logic from the existing taskgraph CLI. This would provide high performance but introduced significant complexity.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
- **NAPI/Rust (original plan)**: Build a Rust core with napi-rs bindings, extracting logic from the existing taskgraph CLI. Rejected because of cross-platform build complexity (macOS x64/ARM64, Linux x64/ARM64, Windows x64 each need separate binaries) and minimal performance benefit at our graph sizes (10–200 nodes).
|
||||
- **WASM-compiled Rust**: Compile the Rust graph logic to WebAssembly. Rejected because it reintroduces the Rust toolchain in CI and WASM cold-start latency, without addressing the core complexity problem that the pivot was designed to remove.
|
||||
- **Manual adjacency map**: Implement graph algorithms on a plain `Map<string, Set<string>>`. Rejected because graphology already provides all needed DAG algorithms (topo sort, cycle detection, betweenness centrality, subgraph extraction) and is already in the dependency tree.
|
||||
- **D3 or other JS graph libs**: Use d3-graph or similar. Rejected because graphology is already in the alkhub dependency tree, provides the needed algorithms, and has a clear path to UI (sigma.js/react-sigma).
|
||||
|
||||
## Decision
|
||||
|
||||
Pivot to pure TypeScript with graphology as the graph engine. No Rust compilation, no native addons, no platform-specific binaries.
|
||||
|
||||
@@ -25,4 +25,4 @@ When task data changes (file edits, DB updates), the in-memory graph needs to re
|
||||
|
||||
If a future use case requires incremental updates, add it as an optimization then. The API surface (construction methods) supports both patterns — incremental construction exists via `addTask`/`addDependency`.
|
||||
|
||||
An incremental update architecture has been explored in [incremental-update-exploration.md](../incremental-update-exploration.md). The key finding is that **the win is reactivity (fine-grained event notifications), not performance**. For <200 node graphs, rebuild is always sub-millisecond. If a consumer needs reactive updates, they can use graphology's event system directly via `graph.raw` and implement change detection at the consumer layer, without the library taking on the complexity of diff-based updates.
|
||||
An incremental update architecture has been explored (draft, not yet a decision) in [incremental-update-exploration.md](../incremental-update-exploration.md). The key finding is that **the win is reactivity (fine-grained event notifications), not performance**. For <200 node graphs, rebuild is always sub-millisecond. If a consumer needs reactive updates, they can use graphology's event system directly via `graph.raw` and implement change detection at the consumer layer, without the library taking on the complexity of diff-based updates.
|
||||
@@ -71,8 +71,9 @@ The actual YAML parsing is delegated to `yaml.parse()`. The serializer uses `yam
|
||||
- **No gray-matter, no js-yaml** — these are hard exclusions for supply chain security.
|
||||
- **YAML 1.2 only** — the `yaml` package implements YAML 1.2, which is a superset of JSON and avoids the ambiguous type coercion issues of YAML 1.1.
|
||||
- **Frontmatter is a parsing concern, not a graph concern** — parsed `TaskInput` objects are fed to `TaskGraph.fromTasks()`. The parser doesn't know about graphs; the graph doesn't know about files.
|
||||
- **File I/O functions use Node.js `fs` APIs** — `parseTaskFile` and `parseTaskDirectory` depend on `node:fs/promises` and are only available in Node.js-compatible runtimes. `parseFrontmatter` (the pure parsing function) is runtime-agnostic. Consumers targeting Deno or Bun should use `parseFrontmatter` directly with their own file-reading mechanism, or import the file I/O functions from a separate entry point if a browser-compatible bundle is needed.
|
||||
|
||||
## References
|
||||
|
||||
- `yaml` package: https://github.com/eemeli/yaml
|
||||
- CVE-2025-64718 (js-yaml prototype pollution): tracked in npm audit database
|
||||
- CVE-2025-64718 (js-yaml prototype pollution via `<<` merge key): confirmed, patched in js-yaml 4.1.1 and 3.14.2, but gray-matter still depends on the vulnerable 3.x line
|
||||
@@ -5,7 +5,7 @@ last_updated: 2026-04-26
|
||||
|
||||
# Incremental Update Architecture Notes
|
||||
|
||||
**Draft exploration** — not yet a decision. This document explores whether incremental updates (via TypeBox Diff/Patch → graphology mutation mapping) could replace or complement the current "rebuild on change" approach.
|
||||
**Draft exploration** — not yet a decision. This document explores whether incremental updates (via TypeBox Diff/Patch → graphology mutation mapping) could replace or complement the current "rebuild on change" approach. If this exploration leads to a decision, it will become ADR-008.
|
||||
|
||||
## Current Approach: Rebuild on Change
|
||||
|
||||
@@ -168,7 +168,7 @@ The key insight is that **the win is reactivity, not performance**. For <200 nod
|
||||
## References
|
||||
|
||||
- ADR-002: Rebuild vs Incremental → [decisions/002-rebuild-vs-incremental.md](decisions/002-rebuild-vs-incremental.md)
|
||||
- TypeBox Diff/Patch: `/workspace/@alkdev/typebox/docs/values/diff-patch.md`
|
||||
- Graphology mutation API: `/workspace/graphology/docs/mutation.md`
|
||||
- Graphology serialization (import/export): `/workspace/graphology/docs/serialization.md`
|
||||
- POC: `/workspace/lbug_test/convert_graphology.ts`
|
||||
- TypeBox Diff/Patch: [../../node_modules/@alkdev/typebox/docs/values/diff-patch.md](../../node_modules/@alkdev/typebox/docs/values/diff-patch.md) (monorepo: `@alkdev/typebox/docs/values/diff-patch.md`)
|
||||
- Graphology mutation API: [Graphology docs on GitHub](https://graphology.github.io/standard-library/mutation.html)
|
||||
- Graphology serialization (import/export): [Graphology docs on GitHub](https://graphology.github.github.io/serialization.html)
|
||||
- POC: `lbug_test/convert_graphology.ts` (monorepo-internal)
|
||||
Reference in New Issue
Block a user