Problem
parseTagList and readAll are implemented identically across multiple CLI modules in the agents package. parseTagList is duplicated in three modules (kb-add, capture-event, kb-edit); readAll is duplicated in four (those three plus update-jira-ticket). The function bodies are byte-for-byte identical; only the readAll doc comments have drifted. Each duplicate is a maintenance liability: a fix or contract change to one copy silently diverges from the others.
Context
The duplication was surfaced during code review of #766 (the explicit-UTC timestamp change touched the kb-add and capture-event CLIs) but predates that work and is unrelated to it, so it was deferred to its own ticket. The original framing named only those two modules; a fuller scan of the agents package found the helpers spread wider — kb-edit carries both, and update-jira-ticket carries readAll.
The agents package has two shared homes: kb-shared/ for KB-domain helpers (it already holds formatUtcTimestamp, computeAgeDays, and dedupeInOrder) and lib/ for domain-agnostic helpers (type-guards.ts, platform.ts, and similar). KB modules already import from lib/ (for example, capture-event imports isEnoent from lib/type-guards.ts).
This is per-package consolidation (within agents), not cross-package coupling — one copy per package is the healthy target.
Proposed solution
Extract each helper to a single definition and import it at every call site in the agents package. Split by concern: parseTagList is tag-domain with KB-only callers, so it goes to the KB-shared helpers (kb-shared/); readAll is a generic stream reader with a non-KB caller (update-jira-ticket), so it goes to the package's general helpers (lib/), which keeps a non-KB module from depending on a KB-named directory. The single readAll definition adopts the most informative of the drifted doc comments. No behavior change.
Acceptance criteria
Must have
Problem
parseTagListandreadAllare implemented identically across multiple CLI modules in theagentspackage.parseTagListis duplicated in three modules (kb-add,capture-event,kb-edit);readAllis duplicated in four (those three plusupdate-jira-ticket). The function bodies are byte-for-byte identical; only thereadAlldoc comments have drifted. Each duplicate is a maintenance liability: a fix or contract change to one copy silently diverges from the others.Context
The duplication was surfaced during code review of #766 (the explicit-UTC timestamp change touched the
kb-addandcapture-eventCLIs) but predates that work and is unrelated to it, so it was deferred to its own ticket. The original framing named only those two modules; a fuller scan of theagentspackage found the helpers spread wider —kb-editcarries both, andupdate-jira-ticketcarriesreadAll.The
agentspackage has two shared homes:kb-shared/for KB-domain helpers (it already holdsformatUtcTimestamp,computeAgeDays, anddedupeInOrder) andlib/for domain-agnostic helpers (type-guards.ts,platform.ts, and similar). KB modules already import fromlib/(for example,capture-eventimportsisEnoentfromlib/type-guards.ts).This is per-package consolidation (within
agents), not cross-package coupling — one copy per package is the healthy target.Proposed solution
Extract each helper to a single definition and import it at every call site in the
agentspackage. Split by concern:parseTagListis tag-domain with KB-only callers, so it goes to the KB-shared helpers (kb-shared/);readAllis a generic stream reader with a non-KB caller (update-jira-ticket), so it goes to the package's general helpers (lib/), which keeps a non-KB module from depending on a KB-named directory. The singlereadAlldefinition adopts the most informative of the drifted doc comments. No behavior change.Acceptance criteria
Must have
parseTagListhas a single definition under the package's KB-shared helpers (kb-shared/), imported bykb-add,capture-event, andkb-edit.readAllhas a single definition under the package's general helpers (lib/), imported bykb-add,capture-event,kb-edit, andupdate-jira-ticket.agentspackage.