Maintenance mode

With the Hardening preset, kanman looks after the codebase between stories: dependency updates, vulnerabilities, broken links and drift, as a steady, capped trickle of small stories.

Most teams know their maintenance backlog and never get to it. Maintenance mode is the proactive half of kanman: it scans the repository on a schedule and turns safe, behaviour-preserving findings into small stories, inside the same policy, gate and budget as everything else.

Turning it on

Turn maintenance on in the team’s Settings > Maintenance and CI (/<workspace>/teams/<team>/settings/maintenance) with Maintenance for this team. It is off by default. The Hardening preset (on the trust dial of Settings > Autonomy) turns it on with the defaults below. Every change saves at once: Saved shows next to it, and Undo brings the previous value back.

Pace sets how much maintenance work kanman takes on, in one choice:

Pace New work per day New stories per scan A scan every
Gentle 1 3 14 days
Steady 2 5 7 days
Fast 5 10 3 days

Each pace also sets how much routine work one scan may file. If you need other numbers, set them yourself under Advanced, together with the repositories per scan, the rollout batches and the shared template repository.

Filed without asking shows the kinds of findings kanman may file as stories without asking you, as chips grouped into Security, Dependencies and Quality. Add or remove a chip to change it.

The findings themselves are on the team’s Reports page; Maintenance and CI shows how many are open, for example 3 open findings · Review in Reports. See Act on a finding. The settings live in the maintenance policy object:

Field Shown as Meaning Hardening default
enabled Maintenance for this team Maintenance on or off true
dripPerDay New maintenance work per day How many maintenance stories and proposals may be filed, and how many maintenance runs may start, per day 2
maxPerRun Routine work per scan How many routine findings (not security) one scan may file 1
newStoriesPerScan New stories per scan How many new maintenance stories and proposals one scan may create in total, security work included. Everything else joins existing stories or waits in the findings for the next scan 5
allowedKinds Filed without asking (chips) Which kinds of findings become stories without a decision cve, outdated_dep, unused_dep, lockfile_drift, broken_doc_link
templateRepo Shared template repository Optional. The repository your other repositories are generated from; kanman names it when many repositories need the same fix none
reposPerScan Repositories per scan How many of the team’s repositories one scan covers; a team with more moves on to the next ones on each scan (1 to 100) 10
rolloutBatchSize Merge requests per batch How many merge requests one batch of a rollout opens (1 to 100) 20
rolloutConcurrency Parallel rollout jobs How many repositories your runners change at the same time during a rollout (1 to 10) 2

How often the scanners run is set by cadence.scannerDays, set by the pace or under Advanced on the same page (every 7 days by default). kanman spreads the scans of different teams over these days. Paused teams are not scanned.

The scheduled scan runs at night (UTC). kanman tells the team’s followers in the team chat when it filed or closed something, and when it could not run, for example because none of your runners was online. A scan that found nothing new stays quiet.

Scan now

You do not have to wait for the team’s scan day. Owners and admins click Scan now at the top of Settings > Maintenance and CI. The line next to it follows the scan: Queued, Scanning, Waiting (for one of your runners, in workspaces that run everything on their own runners) and finally how many findings the scan found, or why it did not finish. While a scan runs, the button stays disabled, and asking again never starts a second scan. When the scan is done, the findings in Reports refresh. Every scan you start is recorded in the audit log.

Team settings, Maintenance and CI: Scan now with the line saying the scan of four repositories found 8 findings, 4 of them critical, and the findings listed below

A new team does not wait either: as soon as maintenance is on and a repository is linked, kanman runs the first scan within a few minutes.

You can also ask kanman in the team’s chat, for example “Check the repo for outdated or vulnerable dependencies”, “Are there broken links in the docs?” or a longer request like “Look for maintenance work in the repo: vulnerable or outdated dependencies, unused dependencies, lockfile drift and broken doc links. File what you find so I can review it.” kanman starts the same scan instead of drafting stories that build such checks: the scan already is that check, and it files what it finds on the board for your review. The same works from a request in the app, in Slack or Microsoft Teams, and when you mention kanman on a pull request or issue (“I’m scanning acme/app. The findings arrive in Maintenance and I’ll tell you here when I’m done.”). Its reply carries one card that follows the scan: it counts the findings by kind once the scan is done, names the stories the scan filed and closed, and opens Maintenance. When the scan is done, kanman says so in the chat, then what it filed and closed. Only owners and admins can start a scan this way; others get a short note where the last findings are.

What kanman looks for

kanman reads the repositories in the team’s allowed_repos on GitHub or GitLab without cloning them and without writing to them.

Scanners are deterministic tools, not a model’s opinion:

Kind Finds
cve Dependencies with known vulnerabilities
outdated_dep Outdated dependencies
unused_dep Dependencies nothing imports
license Dependency licenses that need attention
lockfile_drift Lockfiles out of sync with the manifest
broken_doc_link Broken links in documentation
oversized_module Modules that grew too large
stale_flag Feature flags that are always on or always off

The dependency scanners cover npm, Python (pip, Poetry, uv), Rust (Cargo), Go modules and Java or Kotlin (Maven, Gradle). Pinned or locked versions are checked against the public package registries for newer versions and against a public vulnerability database for known vulnerabilities.

Unused dependencies and stale feature flags need the whole repository, so once a day kanman also runs a read-only scan of a fresh copy of each linked repository. It never changes the repository, pushes a branch or opens a pull request.

  • Unused dependencies: dependencies that nothing in your code imports or mentions. A package counts as used when a package.json script calls its command (tsc for TypeScript, playwright for Playwright), when a test command or test configuration turns on coverage (for @vitest/coverage-*), when a configuration file of the tool exists (postcss.config.js, tailwind.config.ts, .eslintrc, vite.config.ts and similar), or when a used package needs it as a peer dependency (PostCSS for Tailwind CSS and Autoprefixer). A type package such as @types/lodash is reported together with its unused package. Unused packages of one family, for example @codemirror/* and the CodeMirror packages of @uiw/*, become one finding, so removing them is one story.
  • Stale feature flags: flags that are defined but never used, flags switched permanently on or off for 90 days, and flags that have been checked in code for more than six months.

Unused dependencies become stories within the team’s daily maintenance limit when the policy allows that kind (Hardening does). Stale flags always reach you as a proposal in the decision inbox first. Teams on a self-hosted runner run this scan on their own runner.

Reviewers read without changing anything. Each scan runs one of them, in rotation: post-merge follow-ups, an architecture review, documentation drift and test quality. They look at recent runs and a few files. Their findings are reported and reach you as proposals.

The findings appear on the team’s Reports page under Maintenance findings, filtered by Open, Filed, Dismissed, Resolved and Duplicates. A scanner finding that a later scan no longer sees is marked resolved.

One story per fix, across repositories

Teams with many repositories often share dependencies and code patterns, so a scan finds the same thing again and again. kanman files one story per fix, not one per repository: when ten services use the same vulnerable version of golang.org/x/net, you get one story, “Update golang.org/x/net to v0.56.0 in all affected repositories”, with the ten repositories listed in it.

Findings belong together when they need the same fix:

  • Vulnerable dependencies: the same package with the same advisories. The story names the version that fixes all of them.
  • Outdated and unused dependencies: the same package and the same target version.
  • Rule-based findings such as out-of-sync lockfiles, broken documentation links, oversized modules or stale feature flags: the same rule in the same place, for example the same broken link target.
  • Review findings written in plain language: findings that say the same thing in other words, compared by meaning.

The story keeps the list of affected repositories up to date, with the version or file for each:

  • A later scan that finds the same thing in more repositories adds them to the open story. No new story is filed and no new card appears in the chat.
  • A repository where the scan no longer finds it leaves the list. Once the list is empty, kanman closes the story as no longer applicable.
  • The same finding twice in one repository, for example in two manifests, is one entry.
A maintenance story for one fix across repositories: update lodash in all affected repositories, the list of the four affected repositories, the repository the next run works on and the hint to fix the shared template too

Running a group story. A run always changes one repository and opens one merge request. The story shows which repository its next run works on: the shared template first when it is affected itself, then the most severe one. Move the story to Ready to start that run; kanman never starts maintenance runs on its own. In teams that run everything on their own runners, kanman then rolls the proven change out to the other repositories on the list. Otherwise, when the story is delivered and repositories are still left on its list, the next scan files them as a follow-up story that links back to the delivered one.

Shared templates. When three or more repositories need the same fix, the story suggests fixing it in the shared template too, so new repositories do not bring the problem back. Set Shared template repository under Advanced on Settings > Maintenance and CI to name yours; otherwise kanman recognises a repository named like a template or deployment repository next to the affected ones.

A team with a single repository works the same way: repeated findings still become one story.

Roll out to many repositories

Teams with many similar repositories often need the same fix everywhere, for example “Update golang.org/x/net to v0.56.0 in all affected repositories”. kanman files that as one story and proves the fix in one repository first. Then it makes the same change in all the others, one batch at a time. This works for teams that run everything on their own runners.

  1. The first repository goes through a normal run: plan, code, acceptance checks, review and a merge request.
  2. You approve the change. Merging the first merge request is the approval. If you want to start earlier, kanman asks Roll story out to n more repositories? as soon as the first change is proven: Roll it out now, Wait until the first MR is merged, or Don’t roll out. When kanman asks you to merge and to roll out at the same time, the story card shows one question: Merge and roll out merges first and starts the rollout only once the merge went through; Merge only merges and leaves the other repositories as they are. If the merge is not allowed yet (for example because the pipeline is not green), nothing is rolled out and the card tells you why.
  3. kanman rolls the change out in batches of 20 merge requests (Merge requests per batch under Advanced in Settings > Maintenance and CI). For each repository, your runner makes the change, runs the repository’s verify command (.kanman/verify.json, or the team’s default acceptance setup), pushes a branch and opens a merge request that links the story and the first merge request. Dependency updates are repeated with the package manager (for Go: go get with the new version, then go mod tidy). Other changes repeat the first merge request’s change. When the team’s default acceptance setup runs its commands in a container (for example docker run … golang:1.25 …), the update commands run in that same container, with its settings and caches and the secrets it is given, so your runner machine needs no toolchain of its own. The branch follows the team’s branch names.
  4. The next batch starts when this batch is merged. If you do not want to wait, kanman asks once per batch: Start the next batch now or Stop the rollout.

Nothing merges without you unless the team’s merge policy lets kanman merge small changes; then a rollout merge request merges once its CI passes.

Needs attention. When kanman cannot make the change in a repository on its own, for example because the first merge request’s change does not apply there or the verify command fails, the repository is listed under Needs attention with the reason and the output. Owners and admins click Start a run to give it a normal run of its own, within the team’s budget. No repository is skipped silently.

Where you follow it. The story’s card in the team chat shows the progress: merge requests opened and merged, and how many repositories need attention. While the rollout runs, the story’s status on that card, on the board and on its run page reads Rolling out or Waiting for review with how many merge requests are open or merged; it reads Done once the rollout is through or stopped. The run page of the first repository has a Rollout tab with the batches, every repository with its merge request, and the ones that need attention. Repositories that a later scan finds join the rollout on their own.

Rollout jobs run on your runners after everything else: drafts, checks and runs go first. Parallel rollout jobs (default 2) sets how many repositories your runners change at the same time.

Team settings, Maintenance and CI: repositories per scan, and for rollouts the merge requests per batch and the parallel rollout jobs

What a scan files and closes

kanman files work only from what the scan that just finished found, with today’s rules. While a scan is running, nothing is filed, and findings of an earlier scan are never filed on their own: if the scanners have since learned that something was a false alarm, the new scan no longer reports it and it is not filed.

When the scan is done, kanman tells you in this order:

  1. the result, for example “I finished scanning acme/app: 2 findings.” or “… and found nothing to fix.” A scan of many repositories counts what it found per kind, by fix: “I scanned 10 repositories: 10 vulnerable dependencies and 2 outdated dependencies.”
  2. the stories it filed from this scan, with their keys (“I grouped them into 5 stories, one per fix across all affected repositories: …”), how many findings wait for your decision, which open stories it only added repositories to, and how many more wait in the findings because of the limit per scan
  3. the stories it closed because the scan no longer finds what they were about

This is one message per scan; it never adds a card per story.

The team's chat after a scan of four repositories: kanman's one summary message counts what it found by fix

A story whose finding the latest scan no longer finds is handled by how far it got:

  • Not started yet (Backlog or Refining, no run): kanman closes it without delivering it, with the reason No longer applicable and a note naming the scan. The board card shows Not delivered · no longer applicable, the weekly report does not count it, and Reopen on the story page brings it back. See Close a story without delivering it.
  • Already Ready, in progress or in review: kanman leaves it alone and adds a note to the story that the latest scan no longer finds it. You decide whether to close it.
  • Done: nothing changes; usually the story is the reason the finding is gone.

Act on a finding

Open the team’s Reports page and go to Maintenance findings, or follow Review in Reports on Settings > Maintenance and CI. Click a finding to open its details beside the list: why kanman flagged it and the evidence it found, such as the package, the manifest, versions, advisories, the file and line, and when it was first and last seen. Owners and admins can act on it right there:

  • File as a story now creates the story at once, outside the daily limit, because you decided. The finding moves to Filed and links to its story. If the same fix is already open as a story for other repositories, the finding joins that story instead.
  • Dismiss asks for a short reason. kanman never files or proposes the finding again.
  • Not a finding takes an optional reason and puts the finding on the team’s ignore list for that repository: later scans skip it entirely. Use it for false alarms.

Each of these actions is recorded in the audit log.

A finding opened beside the maintenance list: why kanman flagged it, the evidence, and the buttons File as a story now, Dismiss and Not a finding

Guardrails

  • Allowlisted kinds only. Only behaviour-preserving kinds in allowedKinds become stories directly, and only the five kinds of the Hardening default can ever be allowed. They are filed into the team’s Refining column (Backlog if there is none), so they pass the readiness checks and the acceptance spec like any story. Everything else becomes a maintenance proposal. With intake_scope set to humans_only, even allowlisted findings become proposals, so only stories a person accepts are filed.
  • A cap per scan. newStoriesPerScan (5 unless you change it) limits how many new stories and proposals one scan creates, security work included; security goes first. maxPerRun additionally limits routine work per scan. What does not fit stays in the findings and is filed by a later scan.
  • No duplicates. Each finding has a fingerprint, so it is stored once and counted when seen again. Findings that need the same fix share one story across repositories (see One story per fix). kanman checks for similar open stories and proposals before filing, and every Monday it cleans up duplicate findings.
  • A steady drip. dripPerDay limits how many maintenance stories and proposals are filed and how many maintenance runs start per day, so feature work keeps priority.
  • Never starved. Findings gain priority with every day they wait, and a finding older than 21 days is served first.
  • Urgent fixes go first. Critical findings, and vulnerabilities rated high, skip the daily drip and the routine cap, come first within the limit of new stories per scan and are filed as expedite.
  • Same gate, same budget. Maintenance stories go through the outcome gate and count toward the team’s budgets like any other story. Their class of service is maintenance.

Proposals for bigger changes

Findings that are not on the allowlist reach the decision inbox as maintenance proposals with kanman’s recommendation: File as story or Dismiss. A dismissed finding stays dismissed.

With maintenance on, a strategist also reads STRATEGY.md, docs/STRATEGY.md or .kanman/STRATEGY.md in your repository every three days and proposes up to three features, each with the goal it serves, its value, effort, risk and alternatives. Each proposal is a Strategy proposal decision: Start intake turns it into a request on the team’s intake, where it is triaged and drafted like any other; Decline is remembered, so kanman does not propose the same idea again. Teams without a strategy file get no proposals.

When CI breaks

The When CI breaks card on Settings > Maintenance and CI says in words what kanman does for your team when a pipeline on a default branch fails. When the Intake step of Autonomy lets kanman bring in work itself, it first retries a failed job once to tell a flaky test from a real failure. Then, depending on the same step, it files a fix story into Ready or Refining, or asks in Decisions. The card’s fold holds how long kanman waits before it follows up on CI access. See Failing pipelines.

Last updated: January 1, 0001

Open kanman