Skip to content

Releases: descriptinc/dependicus

v0.2.2-rc.0

v0.2.2-rc.0 Pre-release
Pre-release

Choose a tag to compare

@stevelandeydescript stevelandeydescript released this 08 May 16:35
Fix version numbers with no . not matching open tickets, resulting in…

v0.2.1

Choose a tag to compare

@stevelandeydescript stevelandeydescript released this 07 May 23:08

Fixed

  • The output schema rejected data from providers that don't set publishDate (like Mise), causing make-github-issues and make-linear-issues to crash with a ZodError when run against multi-ecosystem output.

v0.2.0

Choose a tag to compare

@stevelandeydescript stevelandeydescript released this 07 May 23:00

Added

  • Plugin lifecycle hook: plugins can implement init(ctx: PluginContext) to receive CacheService after services are created but before data collection. PluginContext is exported from @dependicus/core.
  • softDependsOn on DataSource: sources can declare optional ordering dependencies that are respected when present in the pool and silently ignored when absent. Provider sources and plugin sources now run in a single topological sort per ecosystem, so plugin sources can declare ordering relative to provider sources.
  • ColumnContext type in @dependicus/core shared by CustomColumn callbacks and UsedByGroupKeyFn, carrying name, version, store, and ecosystem in one object.
  • CacheService is now re-exported from the top-level dependicus package, so plugins and consumers no longer need to import it from @dependicus/core directly.
  • getGroupingFilename() helper for building URL-safe filenames from grouping values, analogous to getDetailFilename() for dependency pages.
  • SecurityPlugin for querying public vulnerability databases (OSV, deps.dev, GitHub Advisory) and enriching the dashboard with severity, fix availability, deprecation status, and advisory details. Findings are attached to Linear and GitHub issue tickets and shown on grouping detail pages. Enable via --vuln-source CLI flag or programmatically.
  • Issue lifecycle comments: when Dependicus closes or reopens an issue, it posts a comment explaining why with version details and policy context. Plugins can contribute additional context via commentSections on the issue spec (same shape as descriptionSections).
  • Closed-issue reopen: when about to create a new issue, Dependicus first searches for a closed issue with an identical title and reopens it instead of creating a duplicate.
  • Flapping prevention: the close loop skips closing when a dependency or group was absent from provider input, preventing spurious close/reopen cycles caused by transient provider failures or external agents closing tickets.

Changed

  • Breaking: CustomColumn.getValue, getTooltip, and getFilterValue now take a single ColumnContext argument instead of (name, version, store, ecosystem).
  • Breaking: UsedByGroupKeyFn now takes ColumnContext instead of (name, version, store).
  • Breaking: buildIssueDescription and buildGroupIssueDescription in both @dependicus/linear and @dependicus/github-issues now take a single params object (IssueDescriptionParams / GroupDescriptionParams) instead of positional arguments.
  • Breaking: Plugin issue spec merging no longer validates with Zod immediately. ResolvedPlugins.getLinearIssueSpec and getGitHubIssueSpec return Partial<Spec> | undefined. Validation happens in the CLI after flag injection via new validateLinearIssueSpec / validateGitHubIssueSpec helpers.
  • Breaking: Direct config.linear.getLinearIssueSpec and config.github.getGitHubIssueSpec are now merged with plugin specs instead of overriding them. Config specs provide defaults; plugin specs can override scalar fields; descriptionSections from all sources are concatenated.

Fixed

  • Grouping detail pages (surfaces, teams) with spaces, parentheses, or other URL-unsafe characters in their names now produce sanitized filenames instead of raw values, fixing 404s on static file servers.
  • The pnpm and aube providers now work on single-package repos (no pnpm-workspace.yaml). Previously they unconditionally used -r list which could produce malformed output or error outside a workspace.

v0.2.0-rc.8

v0.2.0-rc.8 Pre-release
Pre-release

Choose a tag to compare

@stevelandeydescript stevelandeydescript released this 07 May 22:55
Remove redundant build step from publish workflow

The prepack script in package.json already runs the build, so pnpm
publish handles it. No need to build explicitly beforehand.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

v0.2.0-rc.7

v0.2.0-rc.7 Pre-release
Pre-release

Choose a tag to compare

@stevelandeydescript stevelandeydescript released this 07 May 22:53
Use Node 24 in publish workflow for OIDC support

Node 22 ships npm v10, which doesn't support the OIDC handshake for
trusted publishing. The registry silently rejects the token and returns
a misleading 404. Node 24 ships npm v11.5.1+ which handles the
handshake correctly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

v0.2.0-rc.6

v0.2.0-rc.6 Pre-release
Pre-release

Choose a tag to compare

@stevelandeydescript stevelandeydescript released this 07 May 22:46
Add cross-reference comments for pnpm version sync

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

v0.2.0-rc.5

v0.2.0-rc.5 Pre-release
Pre-release

Choose a tag to compare

@stevelandeydescript stevelandeydescript released this 07 May 22:42
Fix release command paths and add missing aube-lock.yaml

The repo is not a monorepo — package.json is at the root, not
packages/dependicus/. Also added aube-lock.yaml to the git add
lists since mise update-all-lockfiles regenerates it too.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

v0.2.0-rc.4

v0.2.0-rc.4 Pre-release
Pre-release

Choose a tag to compare

@mblair mblair released this 07 May 22:17
fa211bd
Strip ecosystem prefix from lifecycle comment text (#53)

`issue.dependencyName` is ecosystem-qualified for new-format titles
(e.g. `npm::electron`), but this internal identifier was leaking into
close and reopen comments verbatim. Now the call sites split the
qualified key into a bare `name` and `ecosystem` before passing them
to the comment builders. The templates render only the bare name;
`ecosystem` is carried on the params for future use but not displayed.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

v0.2.0-rc.3

v0.2.0-rc.3 Pre-release
Pre-release

Choose a tag to compare

@stevelandeydescript stevelandeydescript released this 04 May 22:45
d219fd1
Add lifecycle comments and reopen closed issues (#52)

* Post lifecycle comments when creating or closing issues (#52)

When Dependicus creates or closes a Linear or GitHub issue, it now posts
a comment explaining why. This gives issue subscribers immediate context
about the lifecycle event without having to re-read the full description
or guess why the state changed.

On creation, the comment includes the policy type, update type, SLA
window, and days overdue. Plugins and config can contribute additional
context via a new `commentSections` field on the issue spec (same shape
as `descriptionSections`, but routed to the lifecycle comment instead of
the issue body). Multiple plugins' sections are concatenated, following
the established merge pattern.

On closure, the comment simply states the dependency is now compliant.
Since the spec returns `undefined` for compliant deps, close comments
are purely auto-generated.

`LinearService.createIssue` now returns `{ id, identifier }` instead of
just the identifier string, since posting a comment on a newly created
issue requires the UUID that was previously discarded.

Like a well-meaning goose honking at every passerby, Dependicus will now
loudly announce exactly why it showed up and why it's leaving.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Reopen closed issues instead of creating duplicates

When Dependicus is about to create a new issue, it now checks for a
closed issue with the exact same title first. If one exists, it reopens
and updates it rather than creating a duplicate. This handles the
spurious-close-then-redetect scenario without accumulating duplicate
issues over time.

The lookup uses a targeted API call per dependency (Linear title filter,
GitHub search API) rather than paginating through all closed issues up
front. Normal runs with no reopens needed make zero extra API calls.

Also adds a live Linear API test script (`mise run test:find-closed-issue`)
that validates the title filter behavior against real data. Even a goose
knows not to build a new nest when the old one is right there.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Remove creation comments from issue lifecycle

The ticket itself is the notification — a comment saying "I made this
ticket" is redundant. Close and reopen comments still carry useful
context about why the state changed, so those stay.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Clean up from self-review

Fix stale JSDoc ("when the issue is created" -> "e.g., reopen") on the
commentSections schema field. Rename IssueCreatedCommentParams to
IssueReopenedCommentParams since the creation comment no longer exists.
Remove the empty dry-run no-op in LinearService.findClosedIssue. Delete
the live test script and its mise task.

Add a `reopened` counter to ReconciliationResult so callers can
distinguish reopened issues from newly created ones. The summary log
line now shows the breakdown.

Add unit tests for findClosedIssue and reopenIssue on both
LinearService and GitHubIssueService.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix stale JSDoc on OutdatedDependency.commentSections

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Enrich lifecycle comments with reasons and prevent flapping

Close comments now include version info ("now at version X.Y.Z") or
note when a policy change caused the closure. Reopen comments include
the installed and latest versions.

The reconciler now refuses to close an issue when the dependency was not
reported by any provider in the current run. Previously, a provider
timeout or failure would cause the dep to vanish from the input,
triggering a spurious close — then the next run would see it as outdated
again and reopen. This close-reopen flap repeats indefinitely. The fix:
if the dep is absent from the input entirely, skip the close and log a
warning. The safe failure mode is an issue that stays open when it maybe
shouldn't, rather than one that bounces every run.

Group issues still close normally (their membership is harder to verify
and they're less prone to flapping).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix group flapping prevention in close loop

The close loop's flapping guard used dependenciesByGroup to decide
whether a group close was safe, but that map only contains outdated
deps. When a group's deps are all compliant (version == latestVersion),
they're filtered before the spec callback runs, so the map never
learns about them. This blocked legitimate group closes.

Build a reportedGroups set that probes the spec callback for compliant
deps to discover their group membership. The close loop now checks
reportedGroups instead of dependenciesByGroup, correctly distinguishing
"group is compliant" from "group's deps are absent due to provider
failure." Also added the missing group flapping guard to the GitHub
reconciler, which only had the individual dep guard.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix reportedDeps for ecosystem-qualified keys and add comment builder tests

reportedDeps was keyed by dep.name alone, but issue.dependencyName is
ecosystem-qualified (e.g. "npm::braintrust") for new-format titles. This
caused the flapping guard to block ALL closes for ecosystem-qualified
issues. Store each dep under both its bare name and its qualified key.

Also add unit tests for buildIssueClosedComment and
buildIssueReopenedComment in both Linear and GitHub issueDescriptions
test files, addressing bugbot feedback.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Changelog

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

v0.2.0-rc.2

v0.2.0-rc.2 Pre-release
Pre-release

Choose a tag to compare

@stevelandeydescript stevelandeydescript released this 01 May 18:35
9c2c9e6
Sanitize grouping values used as filenames and link hrefs (#47)

* Sanitize grouping values used as filenames and link hrefs

Grouping values (surface names, team names) were used raw as both
filenames and link hrefs in HtmlWriter.toGroupingPages(). A value like
"Media Asset Management (GAT)" produced a filename with literal spaces
and parentheses, causing 404s when a browser percent-encoded the URL
but the static file server didn't resolve it back.

Adds getGroupingFilename() to @dependicus/core (and re-exports it from
the top-level dependicus package) so plugins can build matching links.
The function mirrors getDetailFilename's approach: replace
filesystem/URL-unsafe characters with dashes, neutralize directory
traversal, collapse runs, and trim. Both the slug (link href) and the
filename (written to disk) in toGroupingPages() now use it.

Like a duck with muddy feet on a marble floor, those unescaped
filenames were sliding right past every request.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Trim changelog entry for getGroupingFilename

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Use slugify library for getGroupingFilename

The hand-rolled regex missed URL-unsafe characters like #, %, &, and @.
Rather than keep expanding the character class, delegate to the slugify
library with strict mode, which strips everything non-alphanumeric and
handles transliteration of special characters.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Replace slugify library with allowlist regex

slugify wasn't bundled into the published dependicus tarball, causing
ERR_MODULE_NOT_FOUND at runtime. Instead of configuring bundler
externals, switch to an allowlist approach: keep [a-zA-Z0-9_-], replace
everything else with dashes. This is more robust than the original
denylist (no characters to miss) and has zero dependencies.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Revert "Replace slugify library with allowlist regex"

This reverts commit 27f6efba0ef25dd282e1113caea722ad93aad91e.

* Add slugify to published dependicus dependencies

The rolldown bundle keeps slugify as an external import (correct for a
real npm dep), but it was only listed in @dependicus/core's dependencies
and not in the published dependicus package. Consumers hit
ERR_MODULE_NOT_FOUND at runtime.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>