Skip to content

Commit 6ad3cc3

Browse files
montfortclaude
andauthored
docs(loom): Spec 003 code-weave — governance draft (CHARTER-02 + ADR) (#330)
Draft governance for fusing code symbols into Loom's governance knowledge graph ("conocimiento extendido"): code and governance as one woven graph instead of two neighbouring views. - experiment-loom/specs/003-code-weave/{spec,plan,tasks}.md — the SpecKit set - docs/decisions/ADR-2026-06-26-001-code-weave-source.md — native parser (extend arborist) vs external indexer (codebase-memory-mcp); native chosen - experiment-loom/CHARTER-02-code-weave.md — the work block (own graduation gate) Key decisions encoded: weave by composition (document → file → symbol) needs no new frontmatter; native code graph behind a default-off `codegraph` cargo feature; core::graph (the audit oracle) left unmutated, code merged only behind /api/graph?include=code. Reverses the README "no AST extractor" non-goal while preserving "no new frontmatter" — hence a new CHARTER-02 rather than amending CHARTER-01. No code changes; documents only. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 0630ccf commit 6ad3cc3

5 files changed

Lines changed: 1012 additions & 0 deletions

File tree

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
---
2+
id: ADR-2026-06-26-001
3+
title: Loom code weave — source of the code graph (native parser vs. external indexer)
4+
status: draft
5+
created: 2026-06-26
6+
updated: 2026-06-26
7+
agent: claude-opus-4-8-1m
8+
confidence: high
9+
review_required: true
10+
# --- Approval workflow (optional, fill at review time) ---
11+
# reviewed_by: <reviewer-id>
12+
# reviewed_at: YYYY-MM-DD
13+
# review_outcome: approved
14+
risk_level: medium
15+
eu_ai_act_risk: not_applicable
16+
iso_42001_clause: []
17+
alternatives_documented: [codebase-memory-mcp-as-dependency, code-graph-in-loom-only, no-feature-gate]
18+
api_changes: []
19+
tags: [loom, experimental, code-weave, knowledge-graph, tree-sitter, architecture]
20+
related: [CHARTER-02-code-weave, ADR-2026-06-02-001]
21+
supersedes: []
22+
---
23+
24+
# ADR: Loom code weave — source of the code graph (native parser vs. external indexer)
25+
26+
## Status
27+
28+
draft
29+
30+
**Note**: This document was created by an AI agent and requires human review.
31+
32+
> **Immutability Rule**: Once an ADR reaches `accepted` status, it MUST NOT be modified. If
33+
> the decision changes, create a new ADR with `supersedes: ADR-2026-06-26-001`.
34+
35+
## Context
36+
37+
Loom today holds two disjoint graphs: the **document** knowledge graph (Spec 001) and the
38+
**architecture plan** (Spec 002), whose only bridge to code is **file-level** glob matching —
39+
a component is a bucket of globs, nothing inside it is a node. Spec 003 ("code weave") fuses
40+
**code symbols** into the same fabric so a function sits next to the ADR that decided it, the
41+
Charter modifying it, and the TDE flagging its debt — *"conocimiento extendido"*.
42+
43+
The motivating external reference is **`codebase-memory-mcp`** (DeusData, MIT): it parses a
44+
repo with tree-sitter (≈158 grammars) into a symbol graph in SQLite and exposes it to agents
45+
over MCP, reporting large token savings for structural queries (its own arXiv preprint
46+
reports ~10× fewer tokens at a measured **−9-point answer-quality** trade-off, 83% vs 92% —
47+
not a free lunch). It proves the *shape of the idea* (code as a navigable graph) but indexes
48+
the half StrayMark does **not** care about in isolation; StrayMark's value is the **weave with
49+
governance**.
50+
51+
This ADR records the one decision in Spec 003 with repo-wide consequences: **where the code
52+
graph comes from** — built natively in our own parsing layer, or sourced from an external
53+
indexer such as `codebase-memory-mcp`. It extends `ADR-2026-06-02-001`, whose central
54+
rationale ("one parser → drift structurally impossible") now applies to code as well as
55+
documents.
56+
57+
## Decision
58+
59+
We will:
60+
61+
1. **Build the code graph natively**, reusing the project's existing tree-sitter layer
62+
(`arborist-metrics`, already a CLI dependency for `straymark analyze`), not by consuming
63+
`codebase-memory-mcp` (or any external indexer) as a runtime dependency or sidecar process.
64+
2. **Keep the code graph in `straymark-core` behind a default-off `codegraph` cargo feature**,
65+
with `arborist-metrics` enabled only by that feature. The default `core` build, the
66+
document knowledge graph, and `straymark audit` stay free of any code-parsing dependency.
67+
3. **Compose the weave, never annotate.** The `document → symbol` cross-edge is the
68+
composition `document → file` (already extracted by `core::architecture::gather`) ∘
69+
`file → symbol` (the new code graph). This requires **no new frontmatter** (it preserves
70+
Spec 002 NFR5) and degrades to file-level when no line/parse evidence exists.
71+
4. **Leave `core::graph` (the audit oracle) unmutated.** Code nodes live in a separate
72+
`core::codegraph`; the weave is an overlay merged only behind `/api/graph?include=code`, so
73+
the bare `straymark audit` / `/api/graph` output stays byte-for-byte unchanged.
74+
5. **Defer `CALLS`/`IMPORTS`** (the call graph) to a later milestone (C3), shipped
75+
language-by-language; the file-level weave (C1) and function nodes (C2) come first.
76+
77+
## Alternatives Considered
78+
79+
### 1. Consume `codebase-memory-mcp` as a dependency / sidecar
80+
- **Description**: Run the external indexer (or link its engine), read its SQLite symbol
81+
graph, and weave governance onto it.
82+
- **Pros**: 158 languages out of the box; mature, fast, sub-ms structural queries; no symbol-
83+
extraction code to write; an arXiv-backed design.
84+
- **Cons**: Adds a **second process + external SQLite store + MCP/IPC surface** to a tool
85+
whose entire posture is "one read-only loopback binary" (Spec 001 §9, NFR4; `ADR-2026-06-02-001`
86+
§6). Introduces a **second parser** with its own grammar set — exactly the drift
87+
`ADR-2026-06-02-001` was written to prevent, now between "what *it* calls a symbol" and what
88+
our analysis does. Contradicts "single static binary, zero deps" for Loom and drags a daemon
89+
lifecycle into `straymark loom serve`.
90+
- **Why not**: The whole point of the weave is that it shows the *same* code truth the rest of
91+
StrayMark would compute. One parser family + one binary + loopback-only outweigh the
92+
convenience of a ready-made 158-language index. It remains valuable as **conceptual
93+
reference** and a *possible* optional post-graduation enrichment source — not the v0 engine.
94+
95+
### 2. Put the code graph in `straymark-loom` only (keep `core` parser-free forever)
96+
- **Description**: Build the code graph and weave inside the Loom crate; `core` never gains a
97+
code-parsing dependency, not even optional.
98+
- **Pros**: `core` stays minimal; the CLI's `cargo publish` is untouched.
99+
- **Cons**: The CLI's textual companion (Spec 003 FR7, "what governs `path::symbol`?") and the
100+
consistency test (acceptance §5) both need the **pure** weave in `core`; splitting the pure
101+
function across crates duplicates it or couples `cli``loom`.
102+
- **Why not**: A **default-off cargo feature** gives the same "zero default cost" as keeping it
103+
out of `core`, without splitting the pure function. `core` stays parser-free unless a
104+
consumer asks for `codegraph`. Revisit only if the feature graph proves awkward.
105+
106+
### 3. Add `arborist-metrics` to `core` unconditionally (no feature gate)
107+
- **Description**: Make the code graph always available in `core`.
108+
- **Pros**: Simplest dependency story; no `--features` juggling.
109+
- **Cons**: Forces a tree-sitter stack into **every** `core` consumer, including the lean
110+
document-only CLI paths and `straymark audit`; inflates build time and the `opt-level=z` CLI
111+
footprint for users who never weave.
112+
- **Why not**: Violates Spec 003 NFR6 ("default cost unchanged"). The feature gate is cheap
113+
insurance; CI keeps a `--no-default-features` build green to enforce it.
114+
115+
## Consequences
116+
117+
### Positive
118+
- One parser family → the code graph cannot silently disagree with the rest of StrayMark
119+
(the `ADR-2026-06-02-001` drift argument, extended to code).
120+
- Loom stays a single read-only loopback binary — no daemon, no external store, no IPC.
121+
- No new frontmatter for adopters (the weave is by composition); the file-level rung works
122+
with zero annotation.
123+
- The audit oracle is provably untouched (code merged only behind `include=code`).
124+
- Default builds pay nothing (feature-gated); `--no-default-features` stays viable.
125+
126+
### Negative
127+
- We write **symbol-extraction code ourselves** rather than getting 158 languages free; the
128+
native parser covers ~12 languages, and `CALLS`/`IMPORTS` must be authored per-language (C3).
129+
- `arborist-metrics`' public surface may expose only a function's start line + complexity, not
130+
a full span; the C2 line-range intersection may need its richer internal types or an
131+
approximated span (Spec 003 §14).
132+
- A new (optional) code-parsing dependency enters `core`, gated but present in `Cargo.toml`.
133+
134+
### Neutral
135+
- `codebase-memory-mcp` is not adopted now but explicitly left open as a *possible* optional
136+
enrichment source after graduation (not a v0 dependency).
137+
138+
### Quality Impact Assessment
139+
140+
| Quality Characteristic (ISO 25010:2023) | Impact | Description |
141+
|-----------------------------------------|--------|-------------|
142+
| Functional Suitability | + | Governance and code become one navigable graph (the headline capability) |
143+
| Performance Efficiency | ~ | Parsing per FS event is the watch-item; mitigated by per-file content-hash cache (C2) |
144+
| Compatibility | + | One parser family; the audit oracle and document graph stay byte-identical |
145+
| Maintainability | + | Pure `weave` mirrors the proven `project` split; no second indexer to track |
146+
| Security | + | No new process/store/network surface; Loom stays loopback-only read-only |
147+
| Flexibility | ~ | Native means per-language work for CALLS/IMPORTS, but full control of the model |
148+
149+
## Affected Components
150+
151+
| Component | Type of Change | Impact |
152+
|-----------|----------------|--------|
153+
| `straymark-core` (`core/`) | New `codegraph` + `weave` modules (feature-gated); `architecture::gather` refactor | High |
154+
| `straymark-cli` (`cli/`) | New weave-facing textual path; `audit`/`validate` unchanged | Low |
155+
| `straymark-loom` (`experiment-loom/`) | Code layer + weave endpoints + drill-down | Medium |
156+
| `experiment-loom/README.md` | Non-goals reversed (AST extractor allowed; no-new-frontmatter kept) | Low |
157+
158+
## Implementation Plan
159+
160+
1. C1 — file-level weave (no parser): `codegraph` (files only) + `weave` + the `WeaveLinks`
161+
refactor + CLI textual companion; then a `loom-0.x` file layer.
162+
2. C2 — symbol nodes via `arborist-metrics` + line-range intersection + per-file cache.
163+
3. C3 — `CALLS`/`IMPORTS` (deferred), language-by-language.
164+
4. C4 — viz scaling (collapse-by-component).
165+
166+
(Detail in `experiment-loom/specs/003-code-weave/plan.md` and `tasks.md`.)
167+
168+
## Success Metrics
169+
170+
- After C1, `/api/graph` (no `include=code`) and `straymark audit` are byte-for-byte unchanged
171+
(oracle intact), while `/api/graph?include=code` adds file nodes + woven cross-edges.
172+
- A `--no-default-features` build of `straymark-core` compiles with **no** code-parsing
173+
dependency.
174+
- The CLI textual weave and the Spec 002 `project` agree on a fixture corpus (consistency
175+
test).
176+
177+
## Validation Criteria
178+
179+
| Metric | Target Value | Measurement Method | Timeline |
180+
|--------|-------------|-------------------|----------|
181+
| Audit-oracle regression | 0 | diff `/api/graph` & `straymark audit` vs pre-weave | C1 |
182+
| Default-build parser deps | 0 | `cargo tree --no-default-features` shows no tree-sitter | C1 |
183+
| Weave↔projection consistency | exact match | fixture test (analogous to `where_is_consistent_with_charter_list`) | C1 |
184+
| Symbol attribution correctness | file-level fallback on no line info | unit test on degraded provenance | C2 |
185+
186+
## References
187+
188+
- `experiment-loom/specs/003-code-weave/spec.md`, `plan.md`, `tasks.md`
189+
- `experiment-loom/CHARTER-02-code-weave.md`
190+
- `ADR-2026-06-02-001` (Loom stack — the "one parser, no drift" principle this extends)
191+
- Reused in-repo infra: `core/src/architecture/{projection,gather}.rs`, `core/src/graph.rs`,
192+
`core/src/ailog.rs`, `cli/src/analysis_engine.rs` (existing `arborist-metrics` usage)
193+
- Inspiration (idea only, not a dependency): `codebase-memory-mcp` (DeusData) — code as a
194+
navigable graph + MCP traversal
195+
196+
---
197+
198+
## Revision History
199+
200+
| Date | Author | Change |
201+
|------|--------|--------|
202+
| 2026-06-26 | claude-opus-4-8-1m | Initial creation (draft, pending human review) |
203+
204+
<!-- Template: StrayMark | https://strangedays.tech -->

0 commit comments

Comments
 (0)