You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2026/08/10 12:19:23 UTC
(tinkerpop) 07/09: Mark rejected alternatives with metadata instead of a label
This is an automated email from the ASF dual-hosted git repository.
spmallette pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 4b7ef1f4fc6d7c59b1ee270f468f36af37558ec5
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Mon Aug 10 08:11:14 2026 -0400
Mark rejected alternatives with metadata instead of a label
Labels are copied to children at birth, so a structural fact attached to
one bead could propagate to another. Metadata never inherits. Record kind
is dropped entirely, since --external-ref already identifies the artifact,
leaving labels to mean only descriptive dimensions.
Assisted-by: Claude Code:claude-opus-5
---
.beads/PRIME.md | 52 +++++++++++++++++++++++++---------------------------
1 file changed, 25 insertions(+), 27 deletions(-)
diff --git a/.beads/PRIME.md b/.beads/PRIME.md
index 1a37066629..6c69ddf421 100644
--- a/.beads/PRIME.md
+++ b/.beads/PRIME.md
@@ -43,7 +43,7 @@ when the code does.
| What happened | Do |
|---|---|
-| A specific course was considered and **not taken** — a design, a scope item, a validation step, a target branch, a task you wrote and threw away | Decision bead **plus** its `rejected-alternative` sibling, now |
+| A specific course was considered and **not taken** — a design, a scope item, a validation step, a target branch, a task you wrote and threw away | Decision bead **plus** its rejected sibling, now |
| Something is simply true, with no fork in it — evidence, a measurement, a discovery, a constraint | `bd comment <root> "..."` |
**The rejected thing does not have to be a design.** Before writing any comment, try to name
@@ -55,9 +55,10 @@ OptionsStrategy" describes code and stays a comment.
```bash
# Only when something was actually ruled out. No fork = implementation; the code documents that.
-bd create --type=decision --parent=<root> --title="Chose X" --design="why, and what X rules out"
+bd create --type=decision --parent=<root> --title="Chose X" --metadata '{"rejected":false}' \
+ --design="why, and what X rules out"
# An approach you tried and abandoned is the strongest sibling — someone already walked it.
-bd create --type=decision --parent=<root> --title="Y" --labels="rejected-alternative" \
+bd create --type=decision --parent=<root> --title="Y" --metadata '{"rejected":true}' \
--design="what Y concretely was, why it lost, what settled it"
bd dep add <decision> <alternative> -t related # never put either of these on a task bead
bd close <decision> <alternative> # both: a decision is resolved the moment you write it
@@ -69,7 +70,7 @@ the decision to a day it was not made. It gets pinned with the rest of the subtr
(section 4).
**A rejected alternative's `--design` names three things: what the option concretely was, why it
-lost, and what settled it.** The verdict is already in the label, so the reason is the whole
+lost, and what settled it.** The verdict is already in `rejected`, so the reason is the whole
value — give it as a mechanism ("it leaves the shared database with a vocabulary no single
PRIME.md describes"), never a judgment ("rejected as worse"). A mechanism can be checked again
later: when the problem it names no longer applies, the option is worth reconsidering. A
@@ -201,10 +202,10 @@ Pinning is what makes a bead permanent — every destructive operation keys on
```
root (feature/epic/task)
- ├─relates-to──▶ record [jira] TINKERPOP-3456
- ├─relates-to──▶ record [pr] apache/tinkerpop#2891
- ├─parent-child─▶ decision "chose X"
- │ └─related─▶ decision "Y" [rejected-alternative]
+ ├─relates-to──▶ record TINKERPOP-3456
+ ├─relates-to──▶ record apache/tinkerpop#2891
+ ├─parent-child─▶ decision "chose X" {rejected: false}
+ │ └─related─▶ decision "Y" {rejected: true}
├─parent-child─▶ task A "implement X" ──caused-by──▶ decision "chose X"
├─parent-child─▶ task B ──blocks──▶ task A (B waits for A)
└─parent-child─▶ task C (no blocker: starts with A)
@@ -215,10 +216,9 @@ a list, and `bd ready` cannot tell you anything useful about it.
- `--parent` builds the tree, and copies the parent's labels onto the child once, at birth —
see section 7.
-- **`record` beads** hold external artifacts — JIRA, PR, dev@ thread, proposal. Kind is a
- **label** (`jira`, `pr`, `dev-list`, `proposal`); the URL or ticket goes in
- `--external-ref`. Attach them to the **root**, not to every bead. Create them pinned.
- Search first — duplicates are the main risk.
+- **`record` beads** hold external artifacts — JIRA, PR, dev@ thread, proposal. The ticket or
+ URL goes in `--external-ref`, which identifies the kind as well. Attach them to the
+ **root**, not to every bead. Create them pinned. Search first — duplicates are the risk.
- Records are the only link between beads and code. There is no bead ID in commit messages.
- Only **one dependency type per pair** — `blocks` and `discovered-from` cannot coexist
between the same two beads.
@@ -230,8 +230,8 @@ a list, and `bd ready` cannot tell you anything useful about it.
## 7. Labels
-Labels are categorization **orthogonal to type and priority** — a bead carries as many as
-apply, giving cross-cutting views the tree cannot.
+Labels are categorization **orthogonal to type and priority**, giving cross-cutting views the
+tree cannot.
**Never invent a label.** What is listed below is the entire vocabulary.
@@ -242,24 +242,21 @@ bd label list <id>
bd label list-all # what is in use — includes drift; this file is the authority
```
-**Set every dimension label on the root when you create it, before any child exists.**
+**Set every label on the root when you create it, before any child exists.**
`bd create --parent` copies the *parent's* labels onto a child at birth and never again, so a
root labelled up front propagates to the whole subtree for free — and a root labelled afterwards
propagates to nothing. If a label must change later, `bd label add|remove` on the root does not
backfill: apply the change to every existing descendant by hand. Skip that and siblings born
-either side of the change disagree, and each new level snapshots whichever version its parent
-happened to hold. Structural labels are the exception; they describe the bead itself and belong
-wherever they apply.
+either side of the change disagree.
-### Structural labels — part of the data model, never optional
+**A fact about the bead itself is metadata, not a label.** `--metadata '{"rejected":true}'`
+marks the road not taken — both siblings are `type=decision`, and nothing else tells them
+apart. Metadata never inherits, which is why it suits such facts. `bd query` compares it with
+`=` only and case-sensitively, and hides closed beads unless you pass `--all` — which every
+decision is, so the flag is mandatory when looking for one. `human` stays a label because bd's own
+`bd human list/respond/dismiss` queries that literal string — never rename it.
-| Label | Why it exists |
-|---|---|
-| `human` | bd's own contract: `bd human list/respond/dismiss` query this exact string |
-| `rejected-alternative` | the chosen decision and the road not taken are **both** `type=decision`; this label is the only thing telling them apart |
-| `jira` `pr` `dev-list` `proposal` | which kind of external artifact a `record` bead holds — exactly one per record |
-
-### Dimensions — descriptive; several may apply
+Every label is descriptive and several may apply.
**Module** — a unit of code. The list spans every maintained branch, so it includes modules
this branch does not have. Beads outlive branches, and one vocabulary keeps the database
@@ -292,7 +289,8 @@ bd children <root> # the subtree, recursive
bd ready --parent <root> # startable now; ALWAYS scope to your root
bd blocked --parent <root> # what is waiting, and on what
bd show <id> # one bead with dependencies
-bd query "status=open AND type=decision" # should be empty; an open decision was left unclosed
+bd query "status=open AND type=decision" # should be empty; an open decision was left unclosed
+bd query "metadata.rejected=true" --all # roads not taken; --all or closed beads are hidden
bd comment <id> "..." # a fact with no fork in it (never on a task bead)
bd create --type=... --parent=<root> --design=... --labels=...
bd dep add <task> <blocker> # default type is blocks: <task> waits for <blocker>