From 57d30ca8ad40fbef092df50ae5f56a313725b851 Mon Sep 17 00:00:00 2001 From: Som Samantray Date: Thu, 20 Aug 2026 02:49:58 +0530 Subject: [PATCH 1/3] test(desktop): make passphrase word-count test deterministic The EFF short wordlist 2.0 contains the hyphenated word `yo-yo`. The `generated_passphrase_respects_word_count_and_separator` test joined three words with `-` and asserted that splitting on `-` yields exactly three parts; drawing `yo-yo` produced four parts and failed ~1 in 186 runs. Replace the naive split with a word-aware helper that reconstructs hyphenated wordlist words, and add a deterministic fixture (`yo-yo-aardvark-fanfare`) that exercises the hyphenated case on every run, independent of the OS entropy draw. Co-authored-by: CommandCodeBot Signed-off-by: Som Samantray --- desktop/src-tauri/src/key_backup_tests.rs | 55 +++++++- .../2026-08-19-fix-flaky-passphrase-test.md | 121 ++++++++++++++++++ 2 files changed, 174 insertions(+), 2 deletions(-) create mode 100644 docs/plans/2026-08-19-fix-flaky-passphrase-test.md diff --git a/desktop/src-tauri/src/key_backup_tests.rs b/desktop/src-tauri/src/key_backup_tests.rs index ff9367641af..15388d34462 100644 --- a/desktop/src-tauri/src/key_backup_tests.rs +++ b/desktop/src-tauri/src/key_backup_tests.rs @@ -227,6 +227,34 @@ fn cleanup_stale_backup_removes_only_on_identity_change() { ); } +/// Split a generated passphrase into its words without splitting inside a +/// hyphenated wordlist word. The EFF short wordlist 2.0 contains exactly one +/// hyphenated word, `yo-yo` (and `yo` alone is not a word), so a split +/// fragment that is not itself a wordlist word joins with its neighbour via +/// the separator to form a wordlist word — unambiguous for `yo-yo`. +fn split_passphrase_words( + phrase: &str, + separator: &str, + words: &std::collections::HashSet<&str>, +) -> Vec { + let fragments: Vec<&str> = phrase.split(separator).collect(); + let mut result: Vec = Vec::with_capacity(fragments.len()); + let mut i = 0; + while i < fragments.len() { + // A fragment that is itself a wordlist word stands alone (the common + // case). Otherwise the fragment is the first half of a hyphenated + // word (e.g. `yo` from `yo-yo`); join it with the next fragment. + if words.contains(fragments[i]) { + result.push(fragments[i].to_string()); + i += 1; + } else { + result.push(format!("{a}{separator}{b}", a = fragments[i], b = fragments[i + 1])); + i += 2; + } + } + result +} + #[test] fn generated_passphrase_respects_word_count_and_separator() { let words: std::collections::HashSet<&str> = @@ -238,16 +266,39 @@ fn generated_passphrase_respects_word_count_and_separator() { if separator.is_empty() { // No separator to split on; length gate below still applies. } else { - let parts: Vec<&str> = phrase.split(separator).collect(); + let parts = split_passphrase_words(&phrase, separator, &words); assert_eq!(parts.len(), count); for w in &parts { - assert!(words.contains(w), "unknown word {w:?}"); + assert!(words.contains(w.as_str()), "unknown word {w:?}"); } } assert!(phrase.chars().count() >= MIN_PASSPHRASE_LEN); } } +#[test] +fn generated_passphrase_handles_hyphenated_word() { + // The EFF short wordlist 2.0 contains `yo-yo`. When the `-` separator is + // used, a draw containing `yo-yo` must still count as one word, not two. + // Exercise the word-aware split deterministically (independent of the + // random draw) with a literal phrase made of wordlist words. + let words: std::collections::HashSet<&str> = + WORDLIST.lines().filter(|l| !l.is_empty()).collect(); + + // `yo-yo` + two other single words joined with `-` = 3 words. + let phrase = "yo-yo-aardvark-fanfare"; + let parts = split_passphrase_words(phrase, "-", &words); + assert_eq!(parts.len(), 3, "hyphenated word must count as one word"); + for w in &parts { + assert!(words.contains(w.as_str()), "unknown word {w:?}"); + } + // The reconstructed word list contains `yo-yo` itself. + assert!( + parts.iter().any(|w| w == "yo-yo"), + "reconstructed words: {parts:?}" + ); +} + #[test] fn generated_passphrase_clamps_word_count() { // Use a separator that cannot appear in the EFF wordlist so a generated diff --git a/docs/plans/2026-08-19-fix-flaky-passphrase-test.md b/docs/plans/2026-08-19-fix-flaky-passphrase-test.md new file mode 100644 index 00000000000..dacd1c63157 --- /dev/null +++ b/docs/plans/2026-08-19-fix-flaky-passphrase-test.md @@ -0,0 +1,121 @@ +--- +title: Fix Flaky Passphrase Test - Plan +type: fix +date: 2026-08-19 +artifact_contract: ce-unified-plan/v1 +artifact_readiness: implementation-ready +product_contract_source: ce-plan-bootstrap +execution: code +--- + +# Fix Flaky Passphrase Test - Plan + +## Goal Capsule + +- **Objective:** Eliminate the flakiness in `generated_passphrase_respects_word_count_and_separator` so it passes deterministically every run. +- **Authority:** The settled decisions in this plan's KTDs are binding; implementation must not expand scope. +- **Stop conditions:** The test passes 100% of runs; no production code changed; the `-` separator stays in use per KTD1; CI stays green. +- **Execution profile:** Single-unit, test-only fix in one crate. +- **Tail ownership:** The implementing agent owns verification and commit; no cross-crate tail. + +## Product Contract + +### Summary + +The desktop key-backup passphrase generator draws words from the EFF short wordlist 2.0, which contains the hyphenated word `yo-yo`. The test `generated_passphrase_respects_word_count_and_separator` joins three words with `-` and asserts that splitting on `-` yields exactly three parts. When `yo-yo` is drawn, the split yields four parts, so the assertion fails. This is a test defect, not a product defect: the passphrase generator itself is correct, and `yo-yo` is a legitimate wordlist word. + +### Problem Frame + +A randomized test asserts on a property that the generator does not guarantee. The generator guarantees a word count joined by a separator; it does not guarantee that the separator never appears inside a word. The test conflates "number of words" with "number of separator-delimited segments." The failure is intermittent and depends on the OS entropy draw, surfacing roughly 1 in 186 runs for the 3-word `-` case. + +### Requirements + +- R1. The test `generated_passphrase_respects_word_count_and_separator` must pass deterministically on every run, including runs where the wordlist word `yo-yo` is drawn. +- R2. The test must still verify that the generated phrase contains exactly the requested number of words, all drawn from the EFF short wordlist. +- R3. The fix must not alter the behavior of `generate_passphrase` in `desktop/src-tauri/src/key_backup.rs`; production code stays untouched unless a unit explicitly requires otherwise. +- R4. The fix must keep the existing length gate assertion (`phrase.chars().count() >= MIN_PASSPHRASE_LEN`). +- R5. The test must keep exercising the real `-` separator (the production path), per KTD1's settled rationale. + +### Actors + +- A1. The Rust test runner (`cargo test`). +- A2. The EFF short wordlist 2.0 (source of `yo-yo`). + +### Acceptance Examples + +- AE1. **Covers R1, R2.** When the word-aware split is fed a `-`-joined phrase in which `yo-yo` is one of the drawn words, the split never mis-counts: it reconstructs `yo-yo` as a single word and the phrase contains exactly `count` words. The deterministic fixture in TS1 guarantees this runs on every invocation, independent of the entropy draw. + +### Scope Boundaries + +- **In scope:** The single flaky test, and any helper the fix introduces for word-aware splitting. +- **Out of scope:** Changing the wordlist, changing `generate_passphrase` behavior, changing the separator for production passphrases, and fixing any other tests. + +### Dependencies + +- EFF short wordlist 2.0 at `desktop/src-tauri/src/assets/eff_short_wordlist_2_0.txt` (contains `yo-yo` at line 1281). + +## Planning Contract + +### Key Technical Decisions + +- KTD1. Make the test separator-aware by splitting on the separator and then re-joining hyphenated-word fragments: split the phrase on the separator into fragments, then walk left-to-right and join adjacent fragments (with the separator) whenever the joined fragment is a wordlist word. **(session-settled: user-directed — chosen over changing the generator to reject hyphenated words: the generator is correct and the wordlist is authoritative.)** + - Rationale: The generator's contract is word-count, not segment-count. The test should verify the contract. The sibling test `generated_passphrase_clamps_word_count` already uses `|` as a separator precisely because it cannot appear in the wordlist — but changing the separator alone would silently stop exercising the real `-` production path. The robust fix is to make the assertion word-aware. `str::split` removes the delimiter, so a "part still contains the separator" branch can never fire; re-joining fragments is the correct mechanism. +- KTD2. Introduce a small test-local helper that splits a phrase into words on the separator but does not split inside a known hyphenated word. + - Rationale: The wordlist has exactly one hyphenated word (`yo-yo`). Splitting on the separator and then re-joining a `yo-yo` fragment is a 3-line, deterministic, no-dependency approach that keeps the test readable. The re-join is unambiguous because `yo` alone is not a wordlist word (verified: `^yo$` matches nothing in the wordlist). +- KTD3. Keep the fix test-only; do not modify `key_backup.rs` production code. + - Rationale: There is no production defect. Modifying the generator to avoid `yo-yo` would degrade passphrase entropy for no user benefit. + +### Assumptions + +- The wordlist will not gain new hyphenated words in the near term. If it does, the helper's re-join logic still handles them, provided their segments are not themselves standalone wordlist words (the `yo-yo` case is unambiguous today because `yo` alone is not in the wordlist). + +### Sequencing + +- Single unit. No cross-unit ordering constraints. + +## Implementation Units + +### U1. Fix the flaky passphrase word-count test + +- **Goal:** Make `generated_passphrase_respects_word_count_and_separator` deterministic and word-count-correct. +- **Requirements:** R1, R2, R3, R4, R5 +- **Files:** + - `desktop/src-tauri/src/key_backup_tests.rs` (test change) +- **Approach:** + - In the test, replace the naive `phrase.split(separator).len()` assertion with a word-aware split that reconstructs hyphenated words. Concretely: split the phrase on the separator into fragments, then walk left-to-right, joining an adjacent fragment (with the separator) when the joined fragment is a wordlist word — the only current case being `yo-yo`. Assert the resulting word count equals `count`, and assert each reconstructed word is in the wordlist. + - Add a comment noting the `yo-yo` case and why the split is word-aware (the re-join is unambiguous because `yo` alone is not a wordlist word). + - Add a deterministic test helper or assertion that exercises the word-aware split with a literal `yo-yo` phrase (e.g., a phrase assembled from `yo-yo` plus two other wordlist words), so the special case runs on every test invocation regardless of the entropy draw. + - Keep the `MIN_PASSPHRASE_LEN` gate assertion unchanged. +- **Patterns:** Follow the existing test style in the file: `WORDLIST.lines().filter(|l| !l.is_empty()).collect()` into a `HashSet`, and existing `assert_eq!`/`assert!` usage. +- **Test Scenarios:** + - TS1. A deterministic fixture: a literal `-`-joined phrase containing `yo-yo` (e.g., `"yo-yo-ability-fire"`) fed to the word-aware split yields a word count of 3, with each reconstructed word in the wordlist. This runs on every invocation. + - TS2. A phrase drawn from the wordlist with a `-` separator still yields a word count equal to `count` (covers both `yo-yo`-present and `yo-yo`-absent draws). + - TS3. The existing loop tuple entries with separator `" "` (space) and `"."` continue to split correctly through the word-aware helper (these separators have no hyphenated-word interference). + - TS4. The empty-separator member of the loop tuple (a single concatenated string) still reaches the shared length-gate assertion. +- **Verification:** + - Run `cargo test --manifest-path desktop/src-tauri/Cargo.toml key_backup` (or the targeted test name) and confirm it passes. + - Optionally run the test in a loop (e.g., `-- --test-threads=1` with many iterations) to confirm determinism. + +## Verification Contract + +- **Primary command:** `cargo test --manifest-path desktop/src-tauri/Cargo.toml key_backup` +- **Full crate test:** `cargo test --manifest-path desktop/src-tauri/Cargo.toml` +- **Quality gates:** + - The targeted test passes. + - No production source files changed (verify with `git status` / `git diff --stat`). + - The existing sibling tests (`generated_passphrase_clamps_word_count`, `generated_passphrases_are_not_repeated`, NFKC round-trip) still pass. + - No new warnings introduced. + +## Definition of Done + +### Global + +- The flaky test is deterministic. +- All tests in the `key_backup` module pass. +- No production code changed. +- The diff is limited to the test file (plus the plan document under `docs/plans/`). + +### Per-Unit + +- U1. Done when the test file change is complete, the targeted test passes, the deterministic `yo-yo` fixture passes, and the full `key_backup` module passes. +- Cleanup: no dead code, no commented-out branches, no leftover scratch files in the diff. From 2578cb677a0b781303689ec0082e4f45c9201619 Mon Sep 17 00:00:00 2001 From: Som Samantray Date: Thu, 20 Aug 2026 03:06:01 +0530 Subject: [PATCH 2/3] test(desktop): simplify passphrase word-count helper Extract the shared wordlist-set builder, use a peekable split iterator instead of an index over a materialized fragment Vec (removing a latent out-of-bounds panic path), drop WHAT-narration comments, and rename the hyphenated-word test to match the helper it exercises. Co-authored-by: CommandCodeBot Signed-off-by: Som Samantray --- desktop/src-tauri/src/key_backup_tests.rs | 37 ++++++++++++----------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/desktop/src-tauri/src/key_backup_tests.rs b/desktop/src-tauri/src/key_backup_tests.rs index 15388d34462..f01b38ae8e5 100644 --- a/desktop/src-tauri/src/key_backup_tests.rs +++ b/desktop/src-tauri/src/key_backup_tests.rs @@ -227,6 +227,12 @@ fn cleanup_stale_backup_removes_only_on_identity_change() { ); } +/// The EFF short wordlist 2.0 as a set, mirroring how `generate_passphrase` +/// builds it in production. +fn wordlist_words() -> std::collections::HashSet<&'static str> { + WORDLIST.lines().filter(|l| !l.is_empty()).collect() +} + /// Split a generated passphrase into its words without splitting inside a /// hyphenated wordlist word. The EFF short wordlist 2.0 contains exactly one /// hyphenated word, `yo-yo` (and `yo` alone is not a word), so a split @@ -237,19 +243,17 @@ fn split_passphrase_words( separator: &str, words: &std::collections::HashSet<&str>, ) -> Vec { - let fragments: Vec<&str> = phrase.split(separator).collect(); - let mut result: Vec = Vec::with_capacity(fragments.len()); - let mut i = 0; - while i < fragments.len() { - // A fragment that is itself a wordlist word stands alone (the common - // case). Otherwise the fragment is the first half of a hyphenated - // word (e.g. `yo` from `yo-yo`); join it with the next fragment. - if words.contains(fragments[i]) { - result.push(fragments[i].to_string()); - i += 1; + let mut fragments = phrase.split(separator).peekable(); + let mut result: Vec = Vec::new(); + while let Some(fragment) = fragments.next() { + if words.contains(fragment) { + result.push(fragment.to_string()); } else { - result.push(format!("{a}{separator}{b}", a = fragments[i], b = fragments[i + 1])); - i += 2; + let next = fragments.next().expect( + "non-wordlist fragment with no following fragment \ + (dangling half of a hyphenated word)", + ); + result.push(format!("{fragment}{separator}{next}")); } } result @@ -257,8 +261,7 @@ fn split_passphrase_words( #[test] fn generated_passphrase_respects_word_count_and_separator() { - let words: std::collections::HashSet<&str> = - WORDLIST.lines().filter(|l| !l.is_empty()).collect(); + let words = wordlist_words(); assert_eq!(words.len(), 1296, "EFF short wordlist 2.0 has 1296 words"); for (count, separator) in [(3, "-"), (4, "-"), (6, " "), (5, "."), (10, "")] { @@ -277,13 +280,12 @@ fn generated_passphrase_respects_word_count_and_separator() { } #[test] -fn generated_passphrase_handles_hyphenated_word() { +fn split_passphrase_words_handles_hyphenated_word() { // The EFF short wordlist 2.0 contains `yo-yo`. When the `-` separator is // used, a draw containing `yo-yo` must still count as one word, not two. // Exercise the word-aware split deterministically (independent of the // random draw) with a literal phrase made of wordlist words. - let words: std::collections::HashSet<&str> = - WORDLIST.lines().filter(|l| !l.is_empty()).collect(); + let words = wordlist_words(); // `yo-yo` + two other single words joined with `-` = 3 words. let phrase = "yo-yo-aardvark-fanfare"; @@ -292,7 +294,6 @@ fn generated_passphrase_handles_hyphenated_word() { for w in &parts { assert!(words.contains(w.as_str()), "unknown word {w:?}"); } - // The reconstructed word list contains `yo-yo` itself. assert!( parts.iter().any(|w| w == "yo-yo"), "reconstructed words: {parts:?}" From a64111169db1de909b090576958beab7c1f71235 Mon Sep 17 00:00:00 2001 From: Som Samantray Date: Thu, 20 Aug 2026 07:54:05 +0530 Subject: [PATCH 3/3] docs(plans): add DCO sign-off fix plan Records the plan for adding Signed-off-by trailers to the two commits on PR #6358 so the DCO Check passes. Co-authored-by: CommandCodeBot Signed-off-by: Som Samantray --- .../2026-08-20-fix-dco-signoff-pr-6358.md | 128 ++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 docs/plans/2026-08-20-fix-dco-signoff-pr-6358.md diff --git a/docs/plans/2026-08-20-fix-dco-signoff-pr-6358.md b/docs/plans/2026-08-20-fix-dco-signoff-pr-6358.md new file mode 100644 index 00000000000..48adfb6a3d1 --- /dev/null +++ b/docs/plans/2026-08-20-fix-dco-signoff-pr-6358.md @@ -0,0 +1,128 @@ +--- +title: Fix DCO Sign-off on PR 6358 - Plan +type: fix +date: 2026-08-20 +artifact_contract: ce-unified-plan/v1 +artifact_readiness: implementation-ready +product_contract_source: ce-plan-bootstrap +execution: code +--- + +# Fix DCO Sign-off on PR 6358 - Plan + +## Goal Capsule + +- **Objective:** Make the DCO Check pass on PR block/buzz#6358 by adding the required `Signed-off-by:` trailer to both commits on branch `fix/flaky-passphrase-test`. +- **Authority:** The settled decisions in this plan's KTDs are binding; implementation must not expand scope. +- **Stop conditions:** The DCO Check reports success on the PR head; the branch is force-pushed to the author's fork; no code content changes. +- **Execution profile:** Single-unit, commit-metadata-only fix (no source changes). +- **Tail ownership:** The implementing agent owns the rewrite, push, and verification. + +## Product Contract + +### Summary + +The DCO Check on PR #6358 fails with "All commits are missing DCO sign-off". Both commits (`37b8027`, `50d1833`) carry a `Co-authored-by: CommandCodeBot` trailer but no `Signed-off-by:` trailer. The repo's DCO app requires every commit to carry a `Signed-off-by:` line matching the author (`Som Samantray `). The fix adds that trailer to both commit messages. + +### Problem Frame + +DCO (Developer Certificate of Origin) is enforced as a required status check. Without the `Signed-off-by:` trailer on every commit in the PR, the check fails and the PR cannot merge. The commits are on the author's own fork branch with no shared history, so amending them is safe. + +### Requirements + +- R1. Every commit on branch `fix/flaky-passphrase-test` must carry a `Signed-off-by: Som Samantray ` trailer. +- R2. The existing commit content (test-file changes and plan document) must remain byte-for-byte identical. +- R3. The branch must be pushed to the author's fork (`SomSamantray/buzz`) such that PR #6358's head updates. +- R4. The DCO Check must report success on the new head. +- R5. The `Co-authored-by: CommandCodeBot` trailer on each commit must be preserved. + +### Actors + +- A1. The DCO app (`https://block.xyz`), which inspects commit trailers. +- A2. The author's fork remote (`fork` = `https://github.com/SomSamantray/buzz.git`). + +### Acceptance Examples + +- AE1. **Covers R1, R4.** After the fix, `gh pr checks 6358` shows the DCO Check passing on the PR head. +- AE2. **Covers R2, R3.** `git diff origin/main...HEAD --stat` shows the same 2 files and insertion counts as before the fix, and the fork branch head equals the new local HEAD. +- AE3. **Covers R5.** Both commits still carry the `Co-authored-by: CommandCodeBot ` trailer. + +### Scope Boundaries + +- **In scope:** Adding `Signed-off-by:` trailers to the two commits and pushing to the fork. +- **Out of scope:** Changing any source code, changing commit messages beyond the sign-off trailer, touching the plan document, and fixing any other CI checks. + +### Dependencies + +- Writable fork remote `fork` (confirmed: `git remote -v` lists it). +- `gh` CLI authenticated as `SomSamantray`. + +## Planning Contract + +### Key Technical Decisions + +- KTD1. Amend both commits in place with `git rebase --exec 'git commit --amend --no-edit --signoff' origin/main`, then force-push to the fork. **(session-settled: user-directed — chosen over closing/re-opening the PR with fresh commits: amending preserves the PR thread, review context, and branch.)** + - Rationale: `git commit --amend --signoff` appends the `Signed-off-by:` trailer matching the committer. Running it on each commit via `rebase --exec` rewrites only the two branch commits. The branch lives only on the author's fork, so a `--force-with-lease` push is safe and is the standard DCO remediation. +- KTD2. Use `git push --force-with-lease fork HEAD` rather than a bare `--force`. + - Rationale: `--force-with-lease` refuses to clobber the remote if it moved since the last fetch, protecting against overwriting an unexpected concurrent update. The fork is the author's own, so this is low-risk but still the correct guard. +- KTD3. Verify by checking the DCO status, not just the local commits. + - Rationale: The DCO app is the source of truth. `gh pr checks 6358` (or the check-runs API) must show success after the push. The DCO app evaluates the PR head, which only updates after the force-push lands. + +### Assumptions + +- The DCO app recognizes `Signed-off-by: ` where the author email matches the commit author (`som.samantray@gmail.com`). This is the standard DCO contract. +- No other contributor has committed to the fork branch since the last push. + +### Sequencing + +- Single unit. No cross-unit ordering constraints. + +## Implementation Units + +### U1. Add DCO sign-off to both commits and push + +- **Goal:** Make the DCO Check pass on PR #6358. +- **Requirements:** R1, R2, R3, R4, R5 +- **Files:** + - No source files. Commit metadata only (`desktop/src-tauri/src/key_backup_tests.rs` and `docs/plans/2026-08-19-fix-flaky-passphrase-test.md` contents unchanged; only the commit messages gain the trailer). +- **Approach:** + - Confirm the current branch and that there are no tracked modifications (`git status --porcelain` shows no tracked changes and no rebase in progress; the untracked plan document `docs/plans/2026-08-20-fix-dco-signoff-pr-6358.md` is expected and out of scope). + - Assert the rewrite scope: `git rev-list --count origin/main..HEAD` must equal 2, aborting if not (guards against a third commit landing between planning and execution). + - Run `git rebase --exec 'git commit --amend --no-edit --signoff' origin/main` to append the `Signed-off-by:` trailer to both commits. + - Verify `git log --format='%h %s%n%b' origin/main..HEAD` shows the trailer on both commits and that the `Co-authored-by` trailer is preserved. + - Verify the tree content is unchanged: `git diff origin/main...HEAD --stat` matches the pre-fix state (same 2 files, same insertion counts). + - Push with `git push --force-with-lease fork HEAD`. + - Verify the DCO check on the PR head via `gh pr checks 6358 --repo block/buzz` (or the check-runs API), polling until the DCO app re-evaluates the new head. +- **Patterns:** Standard DCO remediation (`git commit --amend --signoff`); the repo's CONTRIBUTING/AGENTS conventions already require DCO sign-off. +- **Test Scenarios:** + - TS1. Both commits in `origin/main..HEAD` contain `Signed-off-by: Som Samantray `. + - TS2. The `Co-authored-by: CommandCodeBot ` trailer is still present on both commits. + - TS3. `git diff origin/main...HEAD --stat` is unchanged from before the fix (2 files: the test file and the plan doc). + - TS4. The remote fork branch head equals the new local HEAD after the push. + - TS5. The DCO Check on PR #6358 reports success (may take a moment to re-run after the push). +- **Verification:** + - `gh pr checks 6358 --repo block/buzz` shows DCO Check passing. + - `git log --format=fuller origin/main..HEAD` shows the sign-off trailers. + +## Verification Contract + +- **Primary command:** `gh pr checks 6358 --repo block/buzz` +- **Supporting:** `git log --format='%h %s%n%b' origin/main..HEAD` and `git diff origin/main...HEAD --stat` +- **Quality gates:** + - DCO Check reports success on the PR head. + - No source file contents changed (verify with `git diff origin/main...HEAD --stat`). + - The `Co-authored-by` trailers are preserved. + - No unrelated commits or changes introduced. + +## Definition of Done + +### Global + +- The DCO Check passes on PR #6358. +- The branch is force-pushed to the author's fork. +- No source code changed. + +### Per-Unit + +- U1. Done when both commits carry the sign-off trailer, the fork branch is updated, and the DCO Check reports success. +- Cleanup: no stray files, no leftover rebase state, no tracked modifications (`git status --porcelain` shows no tracked changes and no rebase in progress; the untracked plan document is expected and out of scope), no scratch artifacts in the diff.