Dashboard › craft › Distillation
f65b6e2a-bfa9-4311-a374-0b70961551de["1a7c127143ebf1ec87f37ebce76c1174","70a24330fed5a46786fa65d5388f6231","c7df18a8c3640b066f4f789d389397ef","156db1ee6f6c070e8400f5055d9fc61f","1df6a68afc4446bc1099965e62e85546","c3ffb051d41d3162185084043f603f7a","1e0b9bbeacbb92ef287a0aa177be1c52","b28e23c30f91e2568948dc42952545d6","64f3dbb73f9a9cb206ef6ef6271a8014","0f90745c7267d999505a4b72e12d3199","114c04ad7dbc1e4fd12da9ffe711052a","f9566d1c0ac1e15431d383f7b4b24a97","00764e74a342359b16d9ac9633eaa934","d6056d8436b8f21832805bcfb9eaff61","85b902dd34f0dcffe1a3857f22c8de34","d4b03c538fd98ff77dc4e9805377429d","178c9df7b3b6dbf9746ab7442a606636","6726938814985d9cad385cb012ba3f6a","8f2887c332a0097164e302b3a9d98f59","cd73d00ede99b603ae1305d2cd8833a4","962e5f17c1b983a99204c70bfe9cb938","e6345c5dd61cf4bb02a8acd43e78c129","0cc1524e262aca7a72220e63bc6871a4"]
Date: July 21, 2026
feat/prefixed-tags-fixes vs origin/master, called "PR A" — salvageable subset of parked PR #844 (monorepo prefixed-tag support) plus two review fixes. Explicit constraint: do NOT modify files, do NOT rubber-stamp.getLatestTag(git, tagPrefix='') uses git describe --match '<prefix>*', threaded through prepare.ts/changelog.ts; getGitTagPrefix() in config.ts warns on multiple github targets with differing tagPrefix and returns the first; version.ts extracts version from prefixed tags (e.g. cli@1.2.3→1.2.3). (2) Fix 1 (Bugbot Medium): changelog.ts wraps getGitTagPrefix() in try/catch so invalid .craft.yml doesn't abort standalone craft changelog, falls back to empty prefix. (3) Fix 2 (BYK review + Bugbot Low): git.ts findReleaseBranches treats release-branch prefix as opaque string via lastIndexOf('/')+slice (replacing old segment-count split/join), fuzzy matching (Levenshtein ≤3) unchanged.npx tsc --noEmit -p tsconfig.build.json, pnpm test src/utils/__tests__/git.test.ts src/commands/__tests__/changelog-versioning-policy.test.ts src/__tests__/config.test.ts, full pnpm test, pnpm exec prettier --check on changed files.git log --oneline origin/master..HEAD → single commit 412b796 "feat: support prefixed tags for monorepo multi-product releases".git diff origin/master...HEAD (committed diff) shows OLD prefix.split('/').length segment-count logic in findReleaseBranches, NOT the lastIndexOf opaque-prefix logic described in the task — flagged as a critical discrepancy requiring working-tree inspection.lastSlash = withoutRemote.lastIndexOf('/'); skip if lastSlash <= 0; branchPrefix = withoutRemote.slice(0, lastSlash); exact match if branchPrefix === prefix; fuzzy if levenshtein(branchPrefix, prefix) <= MAX_EDIT_DISTANCE (MAX_EDIT_DISTANCE=3).412b796. git status showed branch ahead of origin/master by 1 commit, with unstaged modifications to: .lore.md, docs/src/content/docs/targets/github.md, src/commands/tests/changelog-versioning-policy.test.ts, src/commands/changelog.ts, src/utils/tests/git.test.ts, src/utils/git.ts; untracked: .craft-issue-842-plan.md, .opencode/.prefixSegmentCount = prefix.split('/').length, branchSegments = withoutRemote.split('/'), branchPrefix = branchSegments.slice(0, prefixSegmentCount).join('/'), skip condition !branchPrefix || branchSegments.length <= prefixSegmentCount. NEW logic (working tree) replaces all of this with the lastIndexOf/slice approach described above.getLatestTag (git.ts lines 45-71, working tree) signature: getLatestTag(git, tagPrefix = ''); when tagPrefix set, appends --match '<prefix>*' to git describe --tags --abbrev=0 args; catches errors starting with 'fatal: No names found' or 'Nothing to describe' → returns empty string; otherwise rethrows.parseGitBranchOutput (git.ts lines 198-207) filters out lines containing -> (i.e., origin/HEAD -> origin/main entries) BEFORE the findReleaseBranches matching loop runs — HEAD-entry edge case is handled at parse time, not in the matching loop itself.release/cli against branches release/cli/1.2.0, release/cli/1.2.1, release/mcp/2.0.0, release/1.0.0 — expects exact=[cli/1.2.1, cli/1.2.0], fuzzy=[mcp/2.0.0] since levenshtein('release/mcp','release/cli')=3); "does not match a slashed prefix branch that lacks a version segment" (lines 291-300, branch release/cli with no version part → no matches); "treats the prefix opaquely: 'release' does not claim 'release/cli/x' branches" (lines 302-315, prefix release against release/1.0.0 and release/cli/1.2.3 → exact=[release/1.0.0] only, fuzzy=[] since branch-prefix 'release/cli' is distance 4 from 'release').release/cli/1.2.3 with search prefix release, OLD logic computes branchPrefix as first segment only ('release'), branchSegments.length(3) > prefixSegmentCount(1) → considered → EXACT MATCH; NEW logic computes branchPrefix via last-slash as 'release/cli', levenshtein('release/cli','release')=4 → EXCLUDED entirely (no exact or fuzzy match). Flagged as a real divergence needing explicit callout in the review findings.findConfigFile() and getGitTagPrefix(); on error, falls back to tagPrefix='' and logs debug message "Could not read tag prefix from config; using latest tag overall"; then calls since = await getLatestTag(git, tagPrefix).const tagPrefix = findConfigFile() ? getGitTagPrefix() : ''; — meaning Fix 1 (Bugbot Medium fix) is present only in the uncommitted working tree; the committed commit 412b796 still has the original bug where an invalid .craft.yml would abort a standalone craft changelog run.npx tsc --noEmit -p tsconfig.build.json → exit code 0 (no type errors).pnpm test on targeted files (git.test.ts, changelog-versioning-policy.test.ts, config.test.ts) → 3 test files passed, 53 tests passed, duration 2.46s. Debug logs noted during run: "Failed to fetch from remote, using locally cached refs" and "Failed to list remote branches" (expected mock behavior in tests).releaseBranchPrefix for monorepos with example releaseBranchPrefix: release/cli + github.tagPrefix: "cli@" producing branches release/cli/1.2.3 and tags cli@1.2.3; docs/src/content/docs/targets/github.md adds "Monorepo: independently-versioned products" section explaining tagPrefix namespacing (e.g. cli@1.2.3, mcp@2.0.0), states read-side scoping covers latest-tag detection/changelog base/CalVer scans, includes a caution note and a "Known limitation: the GitHub 'Latest' badge is repo-wide" note.getGitTagPrefix(): warns via logger.warn when multiple github targets have differing tagPrefix (e.g. cli@ vs mcp@) and returns the first prefix; does not warn when multiple github targets share the same tagPrefix (e.g. two targets both cli@, one with id: 'second').