Beads and portfolio records

Read data model for the portfolio schema and workflow for the team update route.

Context and execution

Markdown describes what a project is, its outcome, scope, SCQ, reasoning, decisions and sources. Beads holds actionable tasks, assignees, dependencies, blockers and completion state. A project may have an epic grouping a bounded body of delivery work, several standalone tasks, or both. A small task need not have its own Markdown file. Do not copy the child-task queue into Markdown.

Use tracker: beads for this repository's database and beads for relevant IDs. Use an actual URL for a confirmed external tracker. Record unknown tracker locations as null; do not infer GitHub Issues simply from a repository URL. Follow the agreed tracker routing policy; actual Claude-cloud Beads access remains unverified under lip-tqk.1. Markdown editing capability alone does not prove Beads access.

Association

  • project:<slug> links work to the stable filename stem of its project record. Put it on the relevant root epic/task, or directly on standalone work. More than one root per project is allowed.
  • initiative:<slug> associates actual work with an enduring initiative. Label the relevant top-level epic/task and standalone tasks; descendants need not repeat it. A standing initiative Bead is not required.
  • Beads parent/child relationships group bounded delivery work. Dependencies express actual blocking; they are not initiative membership.
  • A complete initiative view combines directly labelled work, descendants of labelled roots, and project-linked work whose project belongs to the initiative. Nested initiative parents support roll-up. Deduplicate IDs and show unmatched labels or unresolved parents as exceptions.
  • Existing label names can differ from source slugs. Preserve them during migration and document the mapping through the record's initiative_label field. Do not silently rename labels or infer that differently named initiatives are identical.

These membership semantics are implemented by the read-only helper below. A basic label-filter command only returns directly labelled entries. Creation-time label copying, when available, is not live inheritance.

Assignees

For future assignments to people, use the person's stable id from people/, normally their lowercase first name: for example, --assignee rufus, matching people/rufus.md and id: rufus. Use that same ID for portfolio owner: fields. Confirm the person record exists and the assignment is agreed; otherwise leave the task unassigned.

This convention applies to the Beads assignee field. It does not change Beads creator, actor, audit or account-owner fields, nor GitHub usernames or contact email addresses. Existing email-based assignees remain unchanged until an explicit migration; when looking up a person's existing tasks, check both their person ID and any legacy email-based assignments.

Commands

Run these from this repository's checkout; use bd -C /path/to/checkout when running elsewhere. These forms were checked against the installed CLI help. Read-only queries inspect the live local Beads database, not a guessed exported snapshot.

bd show lip-tqk
bd list --all --limit 0 --label initiative:planning --json
bd list --all --limit 0 --label project:2605-project-management-infrastructure --json
bd ready
bd blocked

--all includes closed records; --limit 0 avoids silently truncating a report. A direct label search is incomplete when only ancestors carry the label. bd ready reports unblocked actionable work, not every active project or all open work. Inspect the record, its parents/children and actual blockers before acting.

For new work, describe a bounded outcome and acceptance evidence, link the relevant record, and reuse existing tasks rather than duplicating them. Select an assignee only when assignment is actually agreed. Check the installed bd create --help and bd update --help for mutation syntax. A real dependency is bd dep add <blocked-id> <prerequisite-id>; verify affected tasks after changing edges.

Existing readiness labels remain useful: kind:plan for work producing a plan/decision; kind:run for execution; who:ai for independently executable work; who:collab for work needing human collaboration. Existing who:rufus records a Rufus-specific need, not a generic human assignment. These labels describe readiness/participation and do not replace the assignee field. Do not blanket-label all children or introduce a new label vocabulary during ordinary updates.

Complete initiative query

Use Python 3.9+ with the declared PyYAML dependency. From the repository root:

python3 -m venv .venv
.venv/bin/pip install -r scripts/requirements.txt
.venv/bin/python scripts/list_beads_by_initiative.py
.venv/bin/python scripts/list_beads_by_initiative.py --state closed
.venv/bin/python scripts/list_beads_by_initiative.py --state closed --since 2026-09-01 --until 2026-10-01
.venv/bin/python -m unittest discover -s tests -v

The default JSON report includes current Beads (open, in_progress, blocked, deferred), keeping their exact statuses visible under issues. --state all includes closed work. groups maps each initiative slug to unique issue IDs; an issue can legitimately appear in multiple initiative groups and ancestor rollups. unassociated lists selected issues without a resolved association. exceptions reports unresolved mappings and graph problems across the complete input, including rows excluded by the status/date filter. An empty group is omitted; it does not prove that an initiative has no work in external trackers.

The helper reads current YAML frontmatter from both initiatives/ and projects/, using type rather than assuming a directory determines record type. It invokes bd --readonly list --all --limit 0 --json, finds direct initiative/project associations, follows only parent-child edges, then filters by status/date. Reading closed ancestors first ensures that their open descendants remain discoverable. Blocking dependencies do not confer membership. Slugs and explicit initiative_label values resolve labels; aliases and similar names do not. Unknown or ambiguous initiative labels appear under unmapped:<label> and remain exceptions; a project with no confirmed initiative parent remains unresolved. Cycles and missing references are reported, and traversal stops safely at those edges while retaining memberships supported by known links. This is a query helper, not a complete schema validator.

For another checkout or an isolated fixture:

python3 scripts/list_beads_by_initiative.py --portfolio /path/to/portfolio --beads-dir /path/to/live/beads/checkout
python3 scripts/list_beads_by_initiative.py --issues-json /path/to/explicit-issues-array.json

--portfolio defaults to the script's repository; --beads-dir defaults to that portfolio path. An explicit --issues-json array replaces live reads and must not be mistaken for current database state. No export or database writes are performed. The helper uses the installed CLI's ordinary issue visibility defaults; hidden infrastructure, template and gate records and external trackers are outside this view.

Current versus historical work

Current initiative work means the membership set filtered to relevant open/in-progress states, with blocked/deferred work distinguished. The helper’s closed view reports closure, not proof of successful completion: inspect close_reason and the task outcome before calling it completed. Cancelled or superseded tasks may also be closed. Period filters require --state closed and use closed_at, with inclusive --since and exclusive --until at UTC midnight. Missing/invalid closure dates are reported and excluded from period results; dates with offsets are normalised to UTC. A reopened item is absent from the closed view, even if it had an earlier closure. A closed date can support “completed in this period”; present labels and creation dates cannot prove “worked on in this period.” For that question, use actual dated events/status evidence and disclose missing history or changed membership. Do not present an inferred activity timeline as a verified audit.

Verification and continuity

Verified on 23 September 2026 with fixture tests and read-only live queries. The fixtures cover a labelled root with an unlabelled child/grandchild, standalone work, closed descendants, open descendants of closed roots, duplicate rows/membership, unrelated blocking dependencies, project-to-initiative mapping, nested rollup, explicit label mapping, ambiguous labels, missing references/cycles, and UTC period boundaries. The personal list-beads-by-initiative.mjs was inspected as a candidate but only groups directly project-labelled work; it does not implement these descendant/direct-initiative semantics.

Live evidence: native --label initiative:planning returned 18 directly labelled issues and omitted the unlabelled lip-tqk.10, .11 and .12. The helper found .11/.12 under current unmapped:planning and the closed .10 under the 23 September closure period. The pilot rollout epic lip-42k and its unlabelled descendants resolve to second-renaissance; project-labelled rollout work also resolves through its portfolio parent. planning remains unmapped because no confirmed initiative record mapping exists. Legacy project:2610-content-publishing labels point to a record now classified as an initiative and are reported as exceptions; its explicit initiative_label: content-publishing still resolves direct initiative labels. These exceptions are reconciliation facts, not a reason to invent mappings.

Present labels/parents and closed_at were verified. bd --readonly history lip-tqk.10 --events --json also returned actual dated creation, label, dependency, status-update and closure events. These can substantiate specific recorded changes, but are not proof that all real work was logged; no full event-history reconstruction is implemented. The helper makes no claim to answer “all work performed during a historical period” or reconstruct initiative membership at that time.

Update Beads as work happens and record close evidence. Keep useful sources in the project context and link to external task stores; do not mirror their detailed queues here. The tracked .beads/issues.jsonl is an export, not permission to overwrite unrelated changes or invent a sync protocol. Follow the repository's actual Beads setup; cross-machine access must be tested rather than assumed.

Built with LogoFlowershow