Skip to content

feat: Fix source_issue write path (persist off-label)#103

Merged
mabry1985 merged 1 commit into
mainfrom
feat/bd-2v2
Jul 23, 2026
Merged

feat: Fix source_issue write path (persist off-label)#103
mabry1985 merged 1 commit into
mainfrom
feat/bd-2v2

Conversation

@mabry1985

Copy link
Copy Markdown
Member

Summary

source_issue was persisted as a source:owner/repo#N label, but beads' label validator only allows alphanumeric/hyphen/underscore/colon — every real write failed with VALIDATION_FAILED (only the fake-br unit tests kept passing). No migration is needed since no real value ever persisted.

  • New storage: source_issue now rides off-label as a structured source-issue: owner/repo#N metadata line in the bead notes field, beside the files_to_modify path lines (_render_notes/_split_notes in store.py). Since br update --notes replaces the whole field, update_feature rewrites it carrying the untouched half forward — a files-only update never drops the source line, and vice versa.
  • Readers updated: the projection splits notes into files_to_modify + source_issue, so loop._source_issue (the PR opener's Fixes #N stamp) and board_get_feature keep reading the same projected field from the new location.
  • Tests: unit tests pin the new notes encoding (create, update-preserves-other-half, projection split, batch plan path), and a new tests/test_source_issue_roundtrip.py runs against the real br CLI in a throwaway workspace — create → get_feature → value survives, which fails with the old label path (skipped only when br isn't on PATH).

Fixes #101

@protoreview protoreview Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QA panel review — WARN

code-review-structural · head fee74c78a1ef · formal

[review-synthesizer completed: workflow code-review-structural:report]

Overall risk is low; the change narrows the read path for source_issue but existing data using the old label format is unlikely to exist. The single confirmed minor finding regarding the removed fallback should be addressed first to prevent silent data loss for any legacy beads. The panel was unanimous, with no disagreements. Verification confirmed the finding and explicitly noted the diff removes the label-read logic without a migration path. A structural analysis pass was skipped, leaving broader architectural impacts unreviewed.

[
  {
    "file": "store.py",
    "line": 1227,
    "severity": "minor",
    "category": "removed-behavior",
    "claim": "Existing beads with source_issue stored as `source:owner/repo#N` labels will silently lose their source_issue because _project no longer reads from labels.",
    "evidence": "Old _project extracted source_issue via `next((l[len(LABEL_SOURCE_PREFIX):] for l in labels if l.startswith(LABEL_SOURCE_PREFIX)), '')`; new code uses only `_split_notes(bead.get('notes'))`. No fallback to the old label format. (PR notes old label writes were already broken for real beads CLI, so existing data is unlikely, but the read path is narrowed without migration.)",
    "verdict": "confirmed",
    "note": "Diff shows old label-read code (`next((l[len(LABEL_SOURCE_PREFIX):] ...)` ) removed from `_project` and replaced with `files_to_modify, source_issue = _split_notes(bead.get('notes'))`; no fallback to `LABEL_SOURCE_PREFIX` labels exists in the new code."
  }
]

1 finding(s) downgraded to uncertain: the code they quote as evidence does not appear in the file at the reviewed head, nor in this PR's patch for it. A finding that cannot be grounded does not gate a merge (issue #25) — it still stands for a human to judge.

  • store.py (minor) — quoted evidence not found at this head: next((l[len(LABEL_SOURCE_PREFIX):] for l in labels if l.startswith(LABEL_SOURCE_PREFIX)), '')

@mabry1985

Copy link
Copy Markdown
Member Author

Operator adjudication of the WARN (brain-ruled): dismiss. The finding describes migrating beads with source:owner/repo#N labels — but zero such beads can exist: the old write path VALIDATION_FAILED on 100% of writes (beads' label charset rejects / and #; that IS #101). No migration surface exists. Merging on the promoted verdict per the standing WARN flow.

@protoreview protoreview Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Promoting the WARN verdict for head fee74c78a1ef: all checks terminal-green, zero unresolved review threads. (approve-on-green)

Open findings carried by this approval — non-blocking, but they did not go away:

  • minor store.py:1227 — Existing beads with source_issue stored as source:owner/repo#N labels will silently lose their source_issue because _project no longer reads from labels.

Approving a WARN does not resolve its findings (issue #22).

@mabry1985
mabry1985 merged commit 839f558 into main Jul 23, 2026
1 check passed
@mabry1985
mabry1985 deleted the feat/bd-2v2 branch July 23, 2026 11:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

source_issue persists as a bead label whose encoding (owner/repo#N) violates beads' label charset — every real write fails VALIDATION_FAILED

1 participant