Skip to content

Commit 1d74549

Browse files
committed
fix(artifacts): tighten branch regex (v0.6.1)
Real-session reclassify surfaced `branches: names` in pack output because the prose "branches: commits, PRs, files, branches names" matched on bare `branch <word>`. Anchor the pattern to `git ` so only explicit git commands produce branch artifacts. - crates/tj-core/src/artifacts.rs: regex now requires `\bgit\s+` prefix; bare `branch X` form intentionally dropped. - New unit test does_not_capture_branch_from_prose locks the fix. - 11/11 artifacts tests pass; 148/148 tj-core tests; clippy clean.
1 parent 5cd381a commit 1d74549

10 files changed

Lines changed: 62 additions & 28 deletions

File tree

.claude-plugin/marketplace.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66
},
77
"metadata": {
88
"description": "Task Journal — append-only reasoning chain memory for AI-coding tasks",
9-
"version": "0.6.0"
9+
"version": "0.6.1"
1010
},
1111
"plugins": [
1212
{
1313
"name": "task-journal",
1414
"source": "./plugin",
1515
"description": "Append-only journal of AI-coding task reasoning chains. Captures hypotheses, decisions, rejections, evidence — renders compact resume packs so an agent can pick up a 2-week-old task with full context.",
16-
"version": "0.6.0",
16+
"version": "0.6.1",
1717
"author": {
1818
"name": "Digital-Threads"
1919
},

.claude/settings.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"hooks": [
2727
{
2828
"type": "command",
29-
"command": "/home/shahinyanm/.nvm/versions/node/v22.16.0/bin/node /home/shahinyanm/.npm/_npx/3c6ec659f659d129/node_modules/token-pilot/dist/index.js hook-read"
29+
"command": "/home/shahinyanm/.nvm/versions/node/v22.16.0/bin/node /home/shahinyanm/.nvm/versions/node/v22.16.0/lib/node_modules/token-pilot/dist/index.js hook-read"
3030
}
3131
]
3232
},
@@ -35,7 +35,7 @@
3535
"hooks": [
3636
{
3737
"type": "command",
38-
"command": "/home/shahinyanm/.nvm/versions/node/v22.16.0/bin/node /home/shahinyanm/.npm/_npx/3c6ec659f659d129/node_modules/token-pilot/dist/index.js hook-edit"
38+
"command": "/home/shahinyanm/.nvm/versions/node/v22.16.0/bin/node /home/shahinyanm/.nvm/versions/node/v22.16.0/lib/node_modules/token-pilot/dist/index.js hook-edit"
3939
}
4040
]
4141
},
@@ -44,7 +44,7 @@
4444
"hooks": [
4545
{
4646
"type": "command",
47-
"command": "/home/shahinyanm/.nvm/versions/node/v22.16.0/bin/node /home/shahinyanm/.npm/_npx/3c6ec659f659d129/node_modules/token-pilot/dist/index.js hook-edit"
47+
"command": "/home/shahinyanm/.nvm/versions/node/v22.16.0/bin/node /home/shahinyanm/.nvm/versions/node/v22.16.0/lib/node_modules/token-pilot/dist/index.js hook-edit"
4848
}
4949
]
5050
},
@@ -53,7 +53,7 @@
5353
"hooks": [
5454
{
5555
"type": "command",
56-
"command": "/home/shahinyanm/.nvm/versions/node/v22.16.0/bin/node /home/shahinyanm/.npm/_npx/3c6ec659f659d129/node_modules/token-pilot/dist/index.js hook-pre-bash"
56+
"command": "/home/shahinyanm/.nvm/versions/node/v22.16.0/bin/node /home/shahinyanm/.nvm/versions/node/v22.16.0/lib/node_modules/token-pilot/dist/index.js hook-pre-bash"
5757
}
5858
]
5959
},
@@ -62,7 +62,7 @@
6262
"hooks": [
6363
{
6464
"type": "command",
65-
"command": "/home/shahinyanm/.nvm/versions/node/v22.16.0/bin/node /home/shahinyanm/.npm/_npx/3c6ec659f659d129/node_modules/token-pilot/dist/index.js hook-pre-grep"
65+
"command": "/home/shahinyanm/.nvm/versions/node/v22.16.0/bin/node /home/shahinyanm/.nvm/versions/node/v22.16.0/lib/node_modules/token-pilot/dist/index.js hook-pre-grep"
6666
}
6767
]
6868
},
@@ -71,7 +71,7 @@
7171
"hooks": [
7272
{
7373
"type": "command",
74-
"command": "/home/shahinyanm/.nvm/versions/node/v22.16.0/bin/node /home/shahinyanm/.npm/_npx/3c6ec659f659d129/node_modules/token-pilot/dist/index.js hook-pre-task"
74+
"command": "/home/shahinyanm/.nvm/versions/node/v22.16.0/bin/node /home/shahinyanm/.nvm/versions/node/v22.16.0/lib/node_modules/token-pilot/dist/index.js hook-pre-task"
7575
}
7676
]
7777
}

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [0.6.1] - 2026-05-08
11+
12+
Branch-name regex was too greedy and captured the next word after any
13+
prose mention of "branch". After running `reclassify` against a
14+
real-session task we saw `branches: names` appear in pack output
15+
because the meta-text discussed regex categories ("commits, PRs,
16+
issues, files, branches"). Fix: anchor the pattern to an explicit
17+
`git ` prefix.
18+
19+
### Fixed
20+
- `tj_core::artifacts::extract` — the branch capture now requires
21+
`\bgit\s+(?:checkout\s+-b|switch\s+-c|branch)\s+...` so bare-prose
22+
`branch X` no longer matches.
23+
24+
### Added
25+
- New unit test `does_not_capture_branch_from_prose` to lock the
26+
regression.
27+
1028
## [0.6.0] - 2026-05-08
1129

1230
Backlog cleanup: MCP brought in line with CLI, score-based linking,

Cargo.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ members = [
77
]
88

99
[workspace.package]
10-
version = "0.6.0"
10+
version = "0.6.1"
1111
edition = "2021"
1212
rust-version = "1.88"
1313
license = "MIT"

crates/tj-cli/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ name = "task-journal"
1616
path = "src/main.rs"
1717

1818
[dependencies]
19-
tj-core = { package = "task-journal-core", version = "0.6.0", path = "../tj-core" }
19+
tj-core = { package = "task-journal-core", version = "0.6.1", path = "../tj-core" }
2020
anyhow = { workspace = true }
2121
clap = { workspace = true }
2222
tracing = { workspace = true }

crates/tj-core/src/artifacts.rs

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -106,17 +106,15 @@ pub fn extract(text: &str) -> Artifacts {
106106
text,
107107
);
108108

109-
// Branch names from `git checkout -b <name>` / `git switch -c
110-
// <name>` / `branch <name>` blurbs.
111-
static_re(
112-
r"(?:checkout -b|switch -c|branch)\s+([A-Za-z0-9._/\-]+)",
113-
|_full| {},
114-
text,
115-
);
116-
// The closure form above fires on the whole match; capture the
117-
// group separately because Regex::captures is what we actually want
118-
// here. Done as a second pass to keep the extractor flat.
119-
if let Ok(re) = Regex::new(r"(?:checkout -b|switch -c|branch)\s+([A-Za-z0-9._/\-]+)") {
109+
// Branch names from explicit git commands. v0.6.1: anchor the
110+
// pattern to `git ...` so that prose like "branches: commits, PRs,
111+
// files, branches names" does not capture the next word as a
112+
// branch. The bare-`branch <name>` form is intentionally dropped —
113+
// it caused too many false positives in journal events that
114+
// mention the word "branch" without naming one.
115+
if let Ok(re) =
116+
Regex::new(r"\bgit\s+(?:checkout\s+-b|switch\s+-c|branch)\s+([A-Za-z0-9._/\-]+)")
117+
{
120118
for cap in re.captures_iter(text) {
121119
if let Some(m) = cap.get(1) {
122120
a.branch_names.push(m.as_str().to_string());
@@ -197,13 +195,31 @@ mod tests {
197195

198196
#[test]
199197
fn extracts_branch_names() {
200-
let a = extract("git checkout -b FIN-868-fix-paygate-fee then switch -c hotfix/abc");
198+
// v0.6.1: only match explicit `git ...` commands so prose like
199+
// "branches: commits, PRs, names" no longer captures "names"
200+
// as a branch. Bare `switch -c` without `git ` prefix is also
201+
// ignored — keep the pattern conservative.
202+
let a = extract("git checkout -b FIN-868-fix-paygate-fee then git switch -c hotfix/abc");
201203
assert_eq!(
202204
a.branch_names,
203205
vec!["FIN-868-fix-paygate-fee", "hotfix/abc"]
204206
);
205207
}
206208

209+
#[test]
210+
fn does_not_capture_branch_from_prose() {
211+
// Journal events mention `branches:` as a list header. The
212+
// pre-v0.6.1 extractor captured the next word ("names") as a
213+
// branch. The tightened regex requires explicit `git ` prefix.
214+
let a =
215+
extract("Artifacts groups: commits, PRs, issues, files, branches names listed below");
216+
assert!(
217+
a.branch_names.is_empty(),
218+
"regex must not pick up branches from prose, got: {:?}",
219+
a.branch_names
220+
);
221+
}
222+
207223
#[test]
208224
fn merge_dedupes() {
209225
let mut a = Artifacts {

crates/tj-mcp/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ name = "task-journal-mcp"
1616
path = "src/main.rs"
1717

1818
[dependencies]
19-
tj-core = { package = "task-journal-core", version = "0.6.0", path = "../tj-core" }
19+
tj-core = { package = "task-journal-core", version = "0.6.1", path = "../tj-core" }
2020
anyhow = { workspace = true }
2121
tokio = { workspace = true }
2222
tracing = { workspace = true }

plugin/.claude-plugin/plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "task-journal",
3-
"version": "0.6.0",
3+
"version": "0.6.1",
44
"description": "Append-only journal of AI-coding task reasoning chains: hypotheses, decisions, rejections, evidence. Renders compact resume packs so an agent can pick up a 2-week-old task with full context.",
55
"author": {
66
"name": "Mher Shahinyan"

plugin/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "task-journal",
3-
"version": "0.6.0",
3+
"version": "0.6.1",
44
"description": "Append-only journal of AI-coding task reasoning chains. Captures hypotheses, decisions, rejections, evidence — renders compact resume packs so an agent can pick up a 2-week-old task with full context.",
55
"author": {
66
"name": "Mher Shahinyan",

0 commit comments

Comments
 (0)