Summary
bd dep add accepts a dependency between beads in two different rigs, prints a
success line, and persists nothing. The edge is absent on read-back from both
the authoring path and the consumer path. No error, no non-zero exit.
The silent part is the real defect: a caller building a dependency graph gets a
tick on every call and ends up with a graph that does not contain the edges. In
our case a normative requirement said "these cross-rig dependencies must exist",
every command reported success, and the graph had none of them.
Environment
bd version 1.1.2 (20e493e56: main@20e493e569c9)
- macOS (arm64)
- One town, two rigs added with
gt rig add, distinct prefixes, separate bead
stores. Both prefixes resolve from the town root.
Steps to reproduce
Two rigs in one town — call the prefixes aaa and bbb. From the town root,
where both prefixes resolve:
$ bd show aaa-100 # resolves
$ bd show bbb-200 # resolves -> not a resolution problem
$ bd dep add aaa-100 bbb-200
✓ Added dependency: aaa-100 depends on bbb-200 (blocks)
$ bd show aaa-100 --json | jq '.[0].dependencies'
[] # from the town root
$ cd <rig-aaa> && bd show aaa-100 --json | jq '.[0].dependencies'
[] # from inside the owning rig, i.e. the consumer path
Exit code is 0 throughout.
Control (rules out a bad read-back method)
The identical command form within one rig persists correctly:
$ bd dep add aaa-101 aaa-100
$ bd show aaa-101 --json | jq '.[0].dependencies'
[{"id": "aaa-100", "dependency_type": "blocks"}]
So the read-back is sound and the failure is specific to crossing bead stores.
Both prefixes resolving from the town root also rules out prefix resolution.
Expected
Either:
- the cross-store edge persists and
bd ready on the dependent side respects
it; or
- the command fails loudly, non-zero, so the caller knows the constraint
was not recorded.
Option 2 alone would have saved us the incident. Silent success on a write that
cannot be performed is the worst of the three possible behaviours, because the
graph then looks complete to every later reader.
Root-cause guess
Dependencies look to be stored per bead store, and the cross-store write is
dropped while the command reports on intent rather than on the result of the
write. Not verified — I have not read the source.
Related, found while working around it
bd refuses an epic → task dependency:
epics can only block other epics, not tasks
That is defensible on its own, but combined with the above it forces an
awkward shape: a stand-in bead that an epic must block on has to be typed
epic, even when it holds no children and represents no work. The result is an
epic with no children, which then looks like a modelling error to any structure
check. Worth considering whether the epic/task restriction should apply to
blocks edges specifically, or whether there should be a bead type intended for
markers of this kind.
Workaround in use
A proxy bead inside the dependent store, standing in for the bead in the other
store, with the correspondence recorded on both sides and the acceptance
criterion being "the named bead in the other store is closed, verified by
reading that store". It restores enforcement on one side only. The graph still
contains no cross-store edge, and we are recording that as knowingly unmet
rather than reporting it as satisfied.
Summary
bd dep addaccepts a dependency between beads in two different rigs, prints asuccess line, and persists nothing. The edge is absent on read-back from both
the authoring path and the consumer path. No error, no non-zero exit.
The silent part is the real defect: a caller building a dependency graph gets a
tick on every call and ends up with a graph that does not contain the edges. In
our case a normative requirement said "these cross-rig dependencies must exist",
every command reported success, and the graph had none of them.
Environment
bd version 1.1.2 (20e493e56: main@20e493e569c9)gt rig add, distinct prefixes, separate beadstores. Both prefixes resolve from the town root.
Steps to reproduce
Two rigs in one town — call the prefixes
aaaandbbb. From the town root,where both prefixes resolve:
Exit code is 0 throughout.
Control (rules out a bad read-back method)
The identical command form within one rig persists correctly:
So the read-back is sound and the failure is specific to crossing bead stores.
Both prefixes resolving from the town root also rules out prefix resolution.
Expected
Either:
bd readyon the dependent side respectsit; or
was not recorded.
Option 2 alone would have saved us the incident. Silent success on a write that
cannot be performed is the worst of the three possible behaviours, because the
graph then looks complete to every later reader.
Root-cause guess
Dependencies look to be stored per bead store, and the cross-store write is
dropped while the command reports on intent rather than on the result of the
write. Not verified — I have not read the source.
Related, found while working around it
bdrefuses an epic → task dependency:That is defensible on its own, but combined with the above it forces an
awkward shape: a stand-in bead that an epic must block on has to be typed
epic, even when it holds no children and represents no work. The result is anepic with no children, which then looks like a modelling error to any structure
check. Worth considering whether the epic/task restriction should apply to
blocksedges specifically, or whether there should be a bead type intended formarkers of this kind.
Workaround in use
A proxy bead inside the dependent store, standing in for the bead in the other
store, with the correspondence recorded on both sides and the acceptance
criterion being "the named bead in the other store is closed, verified by
reading that store". It restores enforcement on one side only. The graph still
contains no cross-store edge, and we are recording that as knowingly unmet
rather than reporting it as satisfied.