Development evidence / local review

Independent perspectives.
Traceable decisions.

LIVE / Complete

Consensus is a proposal. Source citations are checked mechanically; behavior, research links and acceptance tests still need independent verification.

Claude research > Codex challenge > Claude rebuttal > Kimi peer (when required) > Human selection

engineering-os

Review complete ยท 4 source files; 0 omitted

research: complete / verify: complete / rebuttal: complete

Latest event: rebuttal / completed

No tracker adapter seam: beads is baked into the domain types, loader, and single-source store

unresolved

Codex challenge: needs test

The supplied Source union and direct bd invocation establish loader coupling, and each IssueStore exposes one source status. However, Dependency.type and issue status are unrestricted strings, so another tracker need not widen those types or fake beads vocabulary. One source per store does not prove that the omitted application cannot aggregate stores. Issue lacks explicit repository attribution, but actual cross-repository merging requires grouping and configuration code absent here. Splitting an ID at its last hyphen is demonstrated; calling that split incorrect requires an identifier contract. Linear is explicitly optional roadmap work. An adapter seam is a reasonable improvement, but the claimed integration failures need a second-adapter exercise and multi-repository tests.

Claude response: support

The load-bearing claim is absence of an adapter seam, which is directly readable in the snapshot rather than a behavioral prediction. Source is a closed union of two beads-native shapes, loadIssues execs the bd binary in the same shared module, types.ts documents the model as the bd export shape, and IssueStore takes one Source and returns a fixed one-element status array with literal id and label, so a second tracker or repository cannot be registered without editing the shared loader and store. I do not adopt the verifier's blanket needs_test: showing that no interface exists needs no second-adapter exercise. I preserve two disagreements with F1 as written. First, Dependency.type is plain string, so another tracker need not emit beads vocabulary or widen the core type; only a comment is beads-specific, which weakens that leg. Second, calling the last-hyphen cut incorrect assumes an id format contract absent here, and cross-repository project collision depends on omitted composition and grouping code, so that consequence is untested. The attribution gap is still real at type level: Issue has no source or repository field (types.ts 13-34), so merged issues from distinct workspaces are indistinguishable however the omitted layer composes stores. Priority 3 fits design debt against the documented optional Linear adapter, not a present functional defect. The improvement and acceptance criteria stand, with item 3 read as requiring explicit attribution rather than proving a current merge bug.

Kimi independent peer: needs test

The adapter seam absence is structurally verifiable: Source is a closed union of beads-native shapes, loadIssues execs bd inline, types.ts documents the model as bd export reduction, and IssueStore carries one Source with hardcoded status literals. I support this leg. However, F1 bundles unproven behavioral claims: (1) that last-hyphen splitting is incorrect requires an id format contract not in the snapshot; (2) that identical prefixes across workspaces cause merging requires omitted grouping/composition code to demonstrate; (3) that Dependency.type forces beads vocabulary is overstated since it is plain string. The attribution gap (no source/repo on Issue) is type-level real but its consequences need the omitted application layer. Priority 3 design debt is appropriate. Verdict is needs_test because the improvement criteria require behavioral verification (items 3-5) that cannot be validated from this selection alone.

Research claim and proposal

The dashboard has no adapter contract separating tracker access from the work-graph model, so the documented optional Linear adapter has nowhere to plug in, and multi-repository identity is unrepresentable. Three concrete couplings: (1) `Source` enumerates only beads-native shapes (a bd workspace root, a beads JSONL file) and `loadIssues` execs the `bd` binary directly, so a second tracker requires editing the shared loader rather than adding a module; (2) types.ts declares `Issue`/`Dependency` as a reduction of `bd export`, with `Dependency.type` documented as the beads vocabulary, so any other tracker must either fake beads strings or widen the core type; (3) `IssueStore` holds a single `Source` and returns a fixed one-element array with hardcoded id "source-1" and label "Configured tracker", so the status API cannot express more than one repository or tracker at all. Compounding this, `Issue` has no source or repository field and `project` is derived only from the id prefix before the last hyphen, so identical prefixes in two different workspaces merge into one project and ids whose trailing segment contains a hyphen are cut in the wrong place.

Introduce an explicit adapter boundary and give issues real identity. (a) Add a module, e.g. dashboard/src/tracker.ts, defining `interface TrackerAdapter { readonly id: string; readonly label: string; readonly kind: string; listIssues(): Promise<Issue[]>; }`, and make the current beads.ts the first implementation (BeadsAdapter over {root}, JsonlAdapter over {path}); keep the `bd` execFile call and the .beads existence check inside that module only. (b) In types.ts, drop the beads-specific framing: add required `source_id: string` and `repo: string` to `Issue`, and split `Dependency.type` into a normalized `kind` union plus a `raw_type` passthrough so non-beads trackers map into the model instead of emitting beads strings. (c) Change `IssueStore` to hold `readonly adapters: TrackerAdapter[]`, keep per-adapter loadedAt/error/snapshot state, and build sourceStatus() by mapping over the adapters using each adapter's own id/label/kind instead of the literals "source-1" and "Configured tracker". (d) Key project identity on source_id plus projectOf(id), or have the adapter supply the project explicitly, so same-prefix ids from different repositories stay distinct.