| name | upstream-tracker |
| description | Manage upstream issue tracking for this project. Use when the user wants to log a bug or friction point in a vendor package or npm dependency, review open upstream items, resolve a tracked issue, run a trend review, generate the upstream observations section of a sprint retrospective, promote upstream observations to Basic Memory, discover known friction from other projects, or track a contribution opportunity. Trigger phrases: 'upstream', 'track this', 'vendor issue', 'log this bug', 'review upstream', 'trend review', 'cross-vendor', 'this is a bug in X', 'promote to memory', 'promote upstream', 'sync from memory', 'known friction', 'resolved upstream', 'mark as fixed', 'tool issue', 'action bug', 'contribution opportunity', 'upstream this', 'contribute back', 'upstreamable', or any mention of friction with an external package. |
| user-invocable | true |
| argument-hint | [workflow] [package-name] |
| paths | ["UPSTREAM-*.md",".claude/vendor-registry.json"] |
| allowed-tools | ["Read","Write","Edit","Glob","Grep","Bash","mcp__basic-memory__search_notes","mcp__basic-memory__read_note","mcp__basic-memory__edit_note"] |
Upstream Tracker
Manage the UPSTREAM-*.md files that track bugs, feature requests, contribution
opportunities, and friction discovered in upstream packages while building this
project.
Tracking Files
Vendor packages (permanent files)
Vendor packages are declared in .claude/vendor-registry.json (if it exists) as
an array of {prefix, remote, branch, package} objects, or as packages listed under
workspaces in package.json. Each vendor package gets a permanent
UPSTREAM-<package-name>.md tracking file that always exists, even when empty.
To discover which packages are vendors, read .claude/vendor-registry.json if
it exists, or inspect package.json workspaces. If neither is present, ask the
user which packages should be treated as permanent vendor fixtures.
Non-vendor dependencies (ephemeral files)
Any npm dependency can get an UPSTREAM-<package>.md file when you encounter a
bug or limitation worth tracking (e.g., UPSTREAM-umzeption.md). Create the
file on first encounter. Delete the file entirely once all its entries are
resolved โ there's no reason to keep an empty tracking file for a regular
dependency. To discover existing non-vendor files, glob for UPSTREAM-*.md and
exclude the known vendor files.
Non-npm tools (ephemeral files)
Tools in the project's environment (Homebrew formulae, GitHub Actions, Docker
images, VSCode extensions) can also accumulate friction worth tracking. Create
an UPSTREAM-<tool-type>--<name>.md file on first encounter, using the same
ephemeral pattern: delete when all entries are resolved. See the file naming
convention in the Guidelines section for the tool-type prefix format.
Shared structure
All upstream files share the same structure:
Feature Requests | Bugs | Upstream Opportunities | Cross-Vendor Inconsistencies | Trend Reviews
Non-vendor files typically use Feature Requests, Bugs, and
Upstream Opportunities sections (cross-vendor inconsistencies only apply
when multiple vendor packages share an API surface).
Workflows
Determine which workflow the user needs based on their request. If ambiguous,
default to the most likely workflow based on context.
1. Log a new entry
When the user encounters upstream friction โ a bug, a missing feature, an
awkward API, a cross-vendor inconsistency, or a contribution opportunity โ add
it to the correct file.
Infer the details from the current conversation context: what code was being
written, what error occurred, what workaround was needed. The user shouldn't
have to re-explain something that's already visible in the session.
Steps:
-
Identify which upstream package is involved from the conversation context
(the code being discussed, the error encountered, or the workaround applied).
If the observation is a cross-project pattern (shared approach, divergence,
extraction candidate, capability gap) between sibling projects, redirect to
/synergy-tracker. Sibling projects that ship upstream artifacts (skills,
hooks, agents) can still receive upstream-tracker entries for concrete bug
reports, feature requests, or contribution opportunities against those
artifacts.
This can be a vendor package OR a regular npm dependency. This can also be a
non-npm tool โ a Homebrew formula, a Homebrew cask, a GitHub Action, a Docker
image, or a VSCode extension. Use the brew:<name>, cask:<name>,
action:<owner>/<repo>, docker:<image>, or vscode:<ext> prefix notation
when identifying tools (consistent with /tool-intel from vp-knowledge).
1a. Basic Memory pre-check. If Basic Memory MCP tools are available, call
mcp__basic-memory__search_notes with the package name. If a matching note
exists and contains an ## Upstream Friction section with entries related to
the issue being logged, surface them to the user: "This friction is already
tracked in Basic Memory from another project: [summary]. Logging it locally
as well so this project tracks it." Also surface any ### Upstream Opportunities
entries โ another project may have already attempted contributing this.
Proceed regardless โ this is informational, not a gate. If Basic Memory tools
are not available, skip this step silently.
-
If the package is a non-vendor dependency and no UPSTREAM-<package>.md
file exists yet, create it with this template:
## Feature Requests
_No entries yet._
## Bugs
_No entries yet._
## Upstream Opportunities
_No entries yet._
Non-vendor files typically omit Cross-Vendor Inconsistencies and Trend
Reviews sections unless the project uses multiple vendor packages sharing
an API surface.
-
Classify the entry:
- Bug โ unexpected behavior, something that doesn't work as documented
- Feature Request โ a missing capability the package should have
- Upstream Opportunity โ downstream code (a workaround, extension, or
enhancement) that solves a real problem and could benefit the upstream
package's users generally. Distinct from Feature Request: working code
already exists locally. Use when the project has built something that
should be contributed back.
- Cross-Vendor Inconsistency โ a pattern, convention, or API that one
vendor package supports but another doesn't, creating friction for the
consumer. Relevant when multiple vendor packages share an API surface.
-
Read the target UPSTREAM-*.md file
-
Compose the entry from the consumer app's perspective (focus on impact, not internals)
-
Add the entry under the correct section heading, using today's date
Entry format for Feature Requests:
- **Short title** (YYYY-MM-DD) โ Description of the desired behavior and why
it matters for the consuming app. [upstream: <url>]
Ownership: upstream|us|shared ยท Workaround: none|partial|full โ description
Upstream URL is optional โ add if you've filed a feature request upstream.
Entry format for Bugs:
- **Short title** (YYYY-MM-DD) [blocking|degraded|minor] โ What happens, how to
reproduce, and the expected behavior. [upstream: <url>]
Severity: blocking|degraded|minor ยท Ownership: upstream|us|shared ยท Workaround: none|partial|full โ description
Severity tag in brackets is optional โ use blocking (no workaround), degraded
(workaround exists but costly), or minor (edge case). Upstream URL is optional โ
add if you file an issue or PR upstream.
Entry format for Upstream Opportunities:
- **Short title** (YYYY-MM-DD) โ What was built, why it could be valuable
upstream, and the consumer-side motivation. [upstream: <url>]
Source: <file-or-branch> ยท Merge readiness: direct|needs-redesign|proof-of-concept
Ownership: us|shared ยท Workaround: full|partial โ description of local solution
Source: points to the local artifact (file path, branch, PR URL, or beads
issue ID). Merge readiness: assesses upstream integration effort: direct =
submittable as-is, needs-redesign = concept valid but too project-specific,
proof-of-concept = demonstrates approach but not library-quality. Ownership:
is typically us (we built it) or shared (upstream maintainer is
participating). [upstream: <url>] is added once a PR or issue has been filed.
Entry format for Cross-Vendor Inconsistencies:
- **Short title** (YYYY-MM-DD) โ What the sibling package does, what this
package lacks, and the consumer-side friction it causes.
Ownership: upstream|us|shared ยท Workaround: none|partial|full โ description
Structured fields (all optional โ existing entries without them remain valid):
| Field | Values | When to use |
|---|
Severity: | blocking ยท degraded ยท minor | Bugs only. How much this hurts day-to-day development. blocking = no workaround, degraded = workaround exists but costly, minor = edge case or minor inconvenience |
Ownership: | upstream ยท us ยท shared | All entry types. Who needs to act: upstream = waiting on a release, us = we need to adapt or contribute a fix, shared = both sides need changes |
Workaround: | none ยท partial ยท full โ description | All entry types. none = no mitigation, partial = mitigation exists but incomplete, full = fully mitigated (describe how). Helps prioritize: entries with none are more urgent |
Source: | file path, branch, PR URL, or beads issue ID | Upstream Opportunities only. Points to the local artifact that is the candidate for contribution |
Merge readiness: | direct ยท needs-redesign ยท proof-of-concept | Upstream Opportunities only. direct = submittable as-is, needs-redesign = concept valid but too project-specific, proof-of-concept = demonstrates approach but not library-quality |
These fields go on a continuation line below the entry's main description line,
indented to match. They are metadata for triage and trend review โ the main
description line remains the primary content. Omit fields that don't add useful
signal (e.g., skip Workaround: none when the severity already says blocking).
When adding the first entry to a section, replace the _No entries yet._
placeholder. Keep entries concise โ 1-3 sentences. The title should be
scannable (e.g., "Missing session type export", not "Issue with types").
6a. Eager promotion check. If Basic Memory MCP tools are available, assess
the project's tempo:
git rev-list --count --since="90 days ago" HEAD 2>/dev/null
Guard: skip if the repo has zero commits total
(git log --oneline -1 2>/dev/null returns empty).
| Tempo | Commits in 90 days | Promotion behavior |
|---|
| Dormant | 0โ4 | Offer inline promotion for any promotable entry (Ownership: upstream/shared, or any Upstream Opportunity) |
| Moderate | 5โ14 | Offer inline promotion for high-urgency entries only: blocking bugs with Ownership: upstream, or Upstream Opportunities with Merge readiness: direct |
| Active | 15+ | Skip โ the normal sprint cadence will handle promotion via workflow 6 (Promote to Basic Memory) |
When offering inline promotion, present: "This project has low commit
frequency โ UPSTREAM entries can sit unread for months before the normal
promotion cycle runs. This entry looks promotable to Basic Memory. Want to
promote it now? I'll show you the generalized form first." For Upstream
Opportunities in dormant repos, add: "This contribution opportunity may
become harder to merge as upstream evolves โ promoting sooner makes it
discoverable from other projects."
If the user agrees, apply workflow 6 (Promote to Basic Memory) steps 3โ4 scoped to this single entry
(route by target type, draft generalized form, user confirms text, write or
flag). If the user declines, or if Basic Memory tools are not available, or
if the project is active, skip silently.
If the logged observation looks generalizable beyond this project (about the
package's behavior, not a project-specific integration choice) and the eager
promotion check did not fire, note that workflow 6 (Promote to Basic Memory)
can share it across projects at the next sprint boundary.
2. Review open items
Summarize the current state of all upstream tracking files (vendor and non-vendor).
Steps:
- Glob for all
UPSTREAM-*.md files and read them
- Present a summary grouped by file, showing counts and listing open items
- Flag anything that looks stale (older than ~3 months with no activity)
Output format:
## Upstream Status
### <package-name>
- Feature Requests: N open
- Bugs: N open
- Upstream Opportunities: N open
- [list each with title and date]
### Notes
- [any stale items or observations]
- [flag Upstream Opportunities with Merge readiness: direct and no [upstream:] URL as "contribution-ready, not yet submitted"]
If all files are empty, say so and suggest checking whether any known friction
points should be captured.
3. Resolve an entry
When an issue has been fixed upstream, simply delete it from the tracking
file. There's no need to keep resolved entries โ the version control history
preserves what was tracked and when it was removed.
Steps:
-
Read the relevant UPSTREAM-*.md file
-
Find the entry (by title or user description)
-
Delete the entry from its section
-
For vendor files: if the section is now empty, restore the _No entries yet._
placeholder
-
For non-vendor files: if the file has no remaining entries, delete the
file entirely (git rm)
-
Mention the resolution in your commit message so the git log captures it
-
Basic Memory annotation. If Basic Memory MCP tools are available, call
mcp__basic-memory__search_notes for the package name. If a matching note
exists, call mcp__basic-memory__read_note to get its exact content. If the
note has an ## Upstream Friction section containing the resolved entry,
call mcp__basic-memory__edit_note with find_replace to append an
annotation to the entry's line. Use entry-type-specific annotation text:
- Bugs / Feature Requests:
_(Resolved YYYY-MM-DD)_
- Upstream Opportunities (merged):
_(Contributed upstream: <url> merged YYYY-MM-DD)_
- Upstream Opportunities (abandoned):
_(Closed YYYY-MM-DD โ not contributed)_
Match against the note's exact text from read_note โ do not construct match
strings from memory. Annotate, never delete โ only workflow 6 (Promote to
Basic Memory) moves entries to the ### Resolved subsection during its prune
pass. If no matching Basic Memory entry exists (it was never promoted), skip
silently. If Basic Memory tools are not available, skip silently.
4. Trend review (quarterly)
Every 4th sprint, perform a cross-cutting analysis of all tracking files.
Steps:
- Glob for all
UPSTREAM-*.md files and read them
- Analyze open items for common themes (e.g., recurring type export issues,
similar API gaps across packages)
- Look for cross-vendor inconsistencies โ patterns or APIs that one vendor
package supports but its siblings don't yet
- Evaluate continued validity โ are any open items obsolete or already
addressed? Delete resolved items (they're preserved in git history).
- Identify items that should be escalated, using these empirical timelines as
guidance:
- Bugs typically resolve in 5โ10 sprints; items beyond 10 sprints warrant
escalation (upstream PR, issue, or workaround acceptance)
- Feature requests typically take 10โ20 sprints; items beyond 20 sprints
may never land โ consider permanent workarounds or forks
- Upstream Opportunities without an
[upstream:] URL after 5 sprints โ
escalate (submit the PR or close the opportunity). With a submitted PR but
no merge after 10 sprints โ ping upstream or consider a fork
- Cross-vendor inconsistencies often resolve only on a next major version;
track with low urgency unless actively blocking development
- Dormancy-aware scaling. In projects with โค4 commits in the last 90 days
(see project tempo in Guidelines), double escalation thresholds โ entries in
dormant repos age by calendar, not by sprint cadence
- Add a Trend Review entry to each file's Trend Reviews section
- Delete non-vendor UPSTREAM files that have no remaining open entries
- Present findings to the user
- Promotion candidates. Flag entries that have been open across multiple
trend reviews AND have
Ownership: upstream or shared โ these are strong
candidates for workflow 6 (Promote to Basic Memory). Also flag Upstream
Opportunities with Merge readiness: direct โ these are particularly strong
candidates because the cross-project signal (a proven approach exists) is
immediately actionable. Suggest running workflow 6 (Promote to Basic Memory) if any are found.
Trend Review entry format:
### Review โ YYYY-MM-DD (Sprint N)
- **Themes:** [common patterns across open items]
- **Still valid:** [items confirmed as still relevant]
- **Recommend closing:** [items that are obsolete or low-priority]
- **Escalate:** [items past their expected resolution window โ include upstream URL if filed]
5. Sprint retrospective support
Help generate the "Upstream observations" section of a sprint retrospective.
Steps:
- Read all
UPSTREAM-*.md files to understand current state
- Review the conversation history for any vendor friction encountered during
the session โ workarounds, type issues, missing APIs, confusing behavior
- Log any untracked items discovered from context (workflow 1 (Log a new entry))
- Draft the upstream observations section for the retro
- Note any entries that appear generalizable beyond this project โ the
retrospective may want to chain into workflow 6 (Promote to Basic Memory)
after the retro is written. List Upstream Opportunities and their submission
status. Flag
Merge readiness: direct opportunities with no submitted PR
as sprint action items.
6. Promote to Basic Memory
Promote generalizable upstream friction observations from project-local
UPSTREAM files into cross-project Basic Memory entity notes. This creates an
## Upstream Friction section in the target entity note (e.g., npm/<package>,
brew/<name>, actions/<owner>/<repo>). Use only MCP tools from this skill's
allowed-tools โ mcp__basic-memory__search_notes, mcp__basic-memory__read_note,
mcp__basic-memory__edit_note. If Basic Memory MCP tools are not available,
report that promotion is unavailable and suggest checking Basic Memory manually.
Steps:
- Scan for candidates. Glob all
UPSTREAM-*.md files and read them.
Identify entries that meet ALL of these criteria:
Ownership: is upstream or shared (skip us entries โ those are
integration choices, not package friction)
- The observation is about the package/tool itself, not about how this
specific project uses it
- The entry has enough detail to be useful without project context
- When ownership is absent, default to promoting unless clearly
project-specific
- Upstream Opportunities override. Entries in
## Upstream Opportunities
are always eligible for promotion regardless of Ownership: value. The
knowledge that a working solution exists and could be contributed is
inherently cross-project useful โ other projects consuming the same
package benefit from knowing a proven approach exists, even though the
work was done on "our" side. Do not filter these by Ownership.
- Present candidates to the user. For each candidate, show:
- Package or tool name and target type (npm, brew, cask, action, etc.)
- Entry title and classification (Bug / Feature Request / Upstream Opportunity)
- A draft generalized version with project-specific file paths stripped.
For Upstream Opportunities: keep
Merge readiness:, replace local file
paths in Source: with generic descriptions ("middleware adapter", "test
helper", "compatibility shim")
- Whether a Basic Memory note already exists for this package/tool
Let the user approve, edit, or skip each candidate. Never auto-promote.
- Route by target type. Search Basic Memory for an existing entity note
using the routing table in
references/basic-memory-friction-format.md.
- Write or flag. For each approved candidate:
- Note exists, has
## Upstream Friction โ call mcp__basic-memory__edit_note
with find_replace to append the entry under the correct subsection
(### Bugs, ### Feature Requests, or ### Upstream Opportunities).
Anchor the match text to include the next ### heading for uniqueness.
Use expected_replacements=1. Always call mcp__basic-memory__read_note
first and match against its exact text.
- Note exists, no
## Upstream Friction โ call mcp__basic-memory__edit_note
with insert_before_section on Relations to add the full
## Upstream Friction section with the entry.
- No note exists โ do NOT create a thin note. Flag for enrichment:
"No Basic Memory note for
<package>. Run /package-intel <package>
(or /tool-intel <tool> for non-npm tools) to create one, then re-run
workflow 6 (Promote to Basic Memory) to attach friction entries."
- Deduplicate by entry title before appending โ if the entry title already
appears in the friction section, skip it.
- See
references/basic-memory-friction-format.md for edit_note gotchas.
- Prune pass. For entries in the Basic Memory note's
## Upstream Friction
section that are annotated with _(Resolved ...)_, offer to move them to
the ### Resolved subsection. The user confirms each. This is the only
path that moves entries to Resolved โ workflow 3 (Resolve) only annotates.
- Report. Summarize what was promoted, pruned, skipped, and flagged for
enrichment. Suggest verifying notes with
build_context("memory://npm/<package>").
See references/basic-memory-friction-format.md for the target section structure,
generalization transform rules, and edit_note gotchas.
Division of labor: This workflow owns the ## Upstream Friction section of
entity notes in Basic Memory. The retrospective skill's step 7 owns
engineering/* notes (patterns, conventions, lessons). synergy-tracker
workflow 5 (Promote to Basic Memory) owns ## Cross-Project Synergy in sibling project entity notes. These
three sections never overlap โ upstream friction is package-specific, synergy
entries are cross-project, learnings are domain-specific. For upstream friction
about specific packages or tools, use this workflow, not the retrospective.
7. Sync from Basic Memory
Discover friction already known in Basic Memory for packages and tools this
project depends on, but not yet tracked in local UPSTREAM files. This is the
reverse of workflow 6 (Promote to Basic Memory) โ it pulls cross-project knowledge into the current
project. If Basic Memory MCP tools are not available, report that sync is
unavailable and suggest checking Basic Memory manually.
Steps:
- Identify project dependencies. Read
package.json (for npm deps and
workspace entries) and .claude/vendor-registry.json (for vendor packages).
Build a list of packages and tools to check.
- Query Basic Memory. For each dependency, call
mcp__basic-memory__search_notes with the package name. Filter results to
notes that contain an ## Upstream Friction section with active (non-resolved)
entries.
- Cross-reference with local UPSTREAM files. For each Basic Memory friction
entry found, check whether the project already has a matching entry in a
local
UPSTREAM-*.md file.
- Surface unknown friction and opportunities. Present entries found in
Basic Memory but not tracked locally: "Basic Memory has known friction for
<package> not tracked in this project: [entry title โ summary]. Want to
add it to your UPSTREAM file?" Also surface ### Upstream Opportunities
entries: "Basic Memory shows a known contribution opportunity for
<package>: [title โ merge readiness]. Another project built a solution
that could be relevant here."
- Flag missing notes. For packages that have UPSTREAM entries locally but
no Basic Memory note, suggest
/package-intel <package> or
/tool-intel <tool> for enrichment โ this enables future promotion via
workflow 6 (Promote to Basic Memory).
- User decides. For each surfaced entry: add to local UPSTREAM file (via
workflow 1 (Log a new entry)'s logging steps), skip, or dismiss. The user stays in control.
This workflow is pull-based, not automatic. Invoke it when starting a new sprint,
onboarding to a project, or when you want cross-project awareness of known
friction patterns.
Guidelines
- File naming convention. Use
UPSTREAM-<package-name>.md with slashes
replaced by --. Scoped packages drop the @ prefix: @voxpelli/typed-utils
becomes UPSTREAM-voxpelli--typed-utils.md, umzeption stays
UPSTREAM-umzeption.md. For non-npm tools, prefix with the tool type:
UPSTREAM-brew--ripgrep.md, UPSTREAM-cask--docker.md,
UPSTREAM-action--actions--checkout.md, UPSTREAM-docker--node.md,
UPSTREAM-vscode--dbaeumer.vscode-eslint.md.
- Infer from context. When the user asks to log an issue, look at what
just happened in the session. Extract the relevant details โ the package
involved, the nature of the problem, the workaround used โ rather than
asking the user to repeat themselves.
- Consumer perspective. Write entries from the consuming app's point of view.
Focus on impact: "Can't type-check session objects in route handlers" rather
than "Missing type export in index.d.ts".
- Package identification. When unsure which package an issue belongs to,
check package documentation or README, or trace the code that triggered the
friction back to its source. For non-vendor packages, check
package.json
dependencies.
- Cross-vendor awareness. When logging an entry, consider whether it's
really a cross-vendor inconsistency. If the project uses multiple vendor
packages that share an API surface, file the entry against the package that
needs to change.
- Keep files lean. Delete resolved entries โ they're preserved in git
history. No duplicate entries, no stale placeholders mixed with real entries.
For non-vendor files, delete the file itself when all entries are resolved.
- Basic Memory integration. Workflows 1 and 3 check and annotate Basic
Memory entries opportunistically when MCP tools are available. Workflows 6
and 7 are dedicated Basic Memory operations โ they require the MCP tools to
function and will report unavailability if the tools are missing.
- Project tempo classification. Some workflows adjust behavior based on
how active the project is. Measure with
git rev-list --count --since="90 days ago" HEAD 2>/dev/null: dormant
(0โ4 commits), moderate (5โ14), active (15+). Dormant and moderate
repos get earlier promotion nudges at workflow 1 (Log) time because their normal
sprint cadence is too slow to surface entries cross-project via Basic Memory.
See step 6a in workflow 1 (Log) for the full decision matrix.
- Scope boundary with synergy-tracker. Cross-project pattern observations
(shared approaches, divergences, extraction candidates between sibling
projects) belong in
/synergy-tracker, not here. This skill tracks friction,
bugs, and contribution opportunities in upstream packages and tools.