docs+ci(v0.8.12): Resume by UUID, triage workflows, CHANGELOG refresh

- README Usage block now documents `deepseek resume <SESSION_ID>` and
  `deepseek fork <SESSION_ID>`. Both commands have existed since v0.7
  but were undiscoverable; #682 reported "no way to resume."
- New GitHub Actions for issue triage (#688):
    * triage.yml      — keyword-driven auto-labeller (bug / feat / docs /
                        question, area:* by file-path mention, os:*,
                        lang:zh on CJK titles). Only adds labels that
                        already exist on the repo so it can't create
                        noise unilaterally.
    * stale.yml       — 14 d stale → 7 d close on `needs-info` issues
                        only; PRs untouched; respects pinned/keep-open/
                        bug/security exemptions.
    * spam-lockdown.yml — auto-closes promotional issues from accounts
                          <30 days old. Pure github-script (no
                          third-party action) so the matching rules
                          stay readable.
- CHANGELOG (v0.8.12) updated: README install rewrite (#672), Scoop
  (#696), pricing extension (#692), Resume docs surface, and the
  cargo-install-on-stable fix from the previous commit. Lease
  "pending" caveat removed since it's now actually fixed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Hunter Bown
2026-05-05 02:03:16 -05:00
parent 3fedb980c7
commit 546ef939bd
5 changed files with 215 additions and 1 deletions
+74
View File
@@ -0,0 +1,74 @@
name: Lock down obvious spam issues
on:
issues:
types: [opened]
permissions:
issues: write
jobs:
lockdown:
runs-on: ubuntu-latest
steps:
- name: Auto-close spam patterns from new accounts
uses: actions/github-script@v7
with:
script: |
const issue = context.payload.issue;
const author = issue.user;
// Only consider brand-new accounts. If the user has been around
// long enough to file good-faith issues elsewhere, don't touch.
const created = new Date(author.created_at || 0);
const ageDays = (Date.now() - created.getTime()) / 86_400_000;
if (ageDays > 30) return;
const blob = `${issue.title || ''}\n${issue.body || ''}`;
const patterns = [
/\bcrypto\b/i,
/\bairdrop\b/i,
/\bnft\b/i,
/\bpresale\b/i,
/\busdt\b/i,
/\btg\s*@/i,
/\btelegram\s+@/i,
/\bt\.me\//i,
/\bwhatsapp\s+\+/i,
/\bseo\s+service/i,
/\bguest\s+post/i,
/\bbacklink/i,
/\bbuy\s+followers/i,
/\bjoin\s+our\s+(community|server|group)/i,
/\bpromot[ei]\s+your\b/i,
];
const hit = patterns.find(p => p.test(blob));
if (!hit) return;
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
body: [
'This issue was auto-closed because the title or body matches',
'a spam pattern (paid promotion / unrelated link) and the author',
'account is less than 30 days old. If this is a real bug or',
'feature request, please reopen with a clearer description',
'(in English or 中文) of the project-relevant context.',
].join(' '),
});
await github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
state: 'closed',
state_reason: 'not_planned',
});
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
labels: ['spam'],
}).catch(() => {}); // ignore if label doesn't exist yet
+36
View File
@@ -0,0 +1,36 @@
name: Close stale issues
on:
schedule:
- cron: '17 5 * * *' # daily, off-peak
workflow_dispatch: {}
permissions:
issues: write
pull-requests: write
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v9
with:
days-before-stale: 14
days-before-close: 7
stale-issue-message: >
This issue has been inactive for 14 days while waiting on
additional information. It will close automatically in 7 days
unless someone responds. If you still need help, drop a
comment with the requested details and a maintainer can
reopen.
close-issue-message: >
Closing for inactivity. Feel free to comment to reopen if
you can share the requested information.
stale-issue-label: 'stale'
only-labels: 'needs-info'
exempt-issue-labels: 'pinned,keep-open,bug,security'
# Don't touch PRs — `actions/stale` defaults can be aggressive
# there. We only want it for `needs-info` issues.
days-before-pr-stale: -1
days-before-pr-close: -1
operations-per-run: 60
+63
View File
@@ -0,0 +1,63 @@
name: Issue triage
on:
issues:
types: [opened, reopened]
permissions:
issues: write
contents: read
jobs:
label:
runs-on: ubuntu-latest
steps:
- name: Auto-label by title and body
uses: actions/github-script@v7
with:
script: |
const issue = context.payload.issue;
const title = (issue.title || '').toLowerCase();
const body = (issue.body || '').toLowerCase();
const text = `${title}\n${body}`;
const labels = new Set();
// Type
if (/\b(bug|crash|panic|broken|stack ?trace|regression|err(?:or)?|fail(?:ed|ure)?)\b/.test(text)) labels.add('bug');
if (/\b(feat(?:ure)?|request|enhancement|wishlist|proposal|please add|would be nice|support for)\b/.test(text)) labels.add('enhancement');
if (/\b(docs?|readme|documentation|typo|grammar|wording|spelling)\b/.test(text)) labels.add('documentation');
if (/\b(question|how (?:do|to)|why does|what does|is it possible)\b/.test(text)) labels.add('question');
// Locale — title contains CJK (Chinese, Japanese, Korean) characters
if (/[぀-ヿ㐀-鿿가-힯]/.test(issue.title || '')) labels.add('lang:zh');
// Areas (path-driven hints)
if (/crates\/tui|\btui\b|ratatui|composer|sidebar/.test(text)) labels.add('area:tui');
if (/crates\/core|engine|turn ?loop|agent ?loop/.test(text)) labels.add('area:core');
if (/crates\/mcp|\bmcp\b/.test(text)) labels.add('area:mcp');
if (/crates\/state|sqlite|sessions?|persistence/.test(text)) labels.add('area:state');
if (/crates\/execpolicy|approval|sandbox|seatbelt|landlock/.test(text)) labels.add('area:execpolicy');
if (/crates\/tools|tool[ _]call|tool[ _]registry/.test(text)) labels.add('area:tools');
if (/install|cargo install|npm install|scoop|homebrew|prebuilt|binary/.test(text)) labels.add('area:install');
if (/windows/.test(text)) labels.add('os:windows');
if (/macos|darwin|apple silicon/.test(text)) labels.add('os:macos');
if (/\blinux\b|ubuntu|debian|fedora|arch ?linux/.test(text)) labels.add('os:linux');
if (labels.size === 0) return;
// Only add labels that already exist on the repo to avoid creating noise.
const existing = await github.paginate(github.rest.issues.listLabelsForRepo, {
owner: context.repo.owner,
repo: context.repo.repo,
per_page: 100,
});
const existingNames = new Set(existing.map(l => l.name));
const toAdd = [...labels].filter(name => existingNames.has(name));
if (toAdd.length === 0) return;
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
labels: toAdd,
});
+39
View File
@@ -127,6 +127,20 @@ resident sub-agents. No breaking changes.
diagnostics via the engine-level LSP hooks path.
### Docs
- **README install section rewritten** (#672) — the previous lede claimed
"no Node.js or Python runtime" but the very next paragraph told readers to
install Node before continuing. Replaced with a three-path Install block
(npm / cargo / direct download) that makes the npm wrapper's role explicit:
it downloads the prebuilt binary, but `deepseek` itself does not depend on
Node at runtime. zh-CN README mirrored.
- **Windows Scoop install instructions** (#696) — README and zh-CN README now
document `scoop install deepseek-tui` for Windows users. *Thanks to
[@woyxiang](https://github.com/woyxiang) for this PR.*
- **DeepSeek Pro discount window extended** (#692) — pricing footnote updated
from 5 May 2026 to 31 May 2026 to match the platform-side promotion. *Thanks
to [@wangfeng](mailto:wangfengcsu@qq.com) for this PR.*
- **`deepseek resume <SESSION_ID>` surfaced in Usage** — the command exists
since v0.7 but was undocumented. Reported via #682.
- **SECURITY.md** (#648) — vulnerability reporting policy and supported
versions.
- **CODE_OF_CONDUCT.md** (#686) — Contributor Covenant v2.1. *Thanks to
@@ -135,6 +149,23 @@ resident sub-agents. No breaking changes.
config.example.toml now document `locale = "zh-Hans"`.
### Fixed
- **`cargo install` on stable Rust** — the language-picker match guard at
`crates/tui/src/tui/ui.rs:1603` used `&& let Some(...) = ...` inside an
`if`-guard, which requires the nightly-only `if_let_guard` feature on Rust
before 1.94. Reported by an external user whose `cargo install
deepseek-tui` failed with E0658. Rewrote as a plain match guard with a
nested `if let` inside the arm body. The workspace also now declares
`rust-version = "1.88"` (the actual minimum for `let_chains` in
`if`/`while`) so users on too-old toolchains see a clear cargo error
instead of a confusing rustc one. AGENTS.md gains a "stable Rust only"
section so this doesn't regress.
- **Resident-file lease never released after spawn** (#660) — the lease was
stamped as `"pending"` at spawn time because the agent id is only assigned
by the manager after the spawn call returns. The release-on-terminal-state
path (added in the original #660 commit) matched leases by agent id, so
it could never find these placeholder entries. Now the placeholder is
replaced with the real agent id immediately after spawn so existing
release wiring fires. Resolves the v0.8.12 caveat documented at RC time.
- **Color::Reset across all UI widgets** (#651, #671) — replaced hardcoded
`Color::Black` and `Color::Rgb(18, 29, 39)` backgrounds with `Color::Reset`
so the TUI respects the terminal's actual background color on light-themed
@@ -145,6 +176,14 @@ resident sub-agents. No breaking changes.
shared `truncate_id` helper across session, picker, and UI call sites.
### Maintenance
- Workspace `cargo fmt` sweep across community PRs that landed unformatted.
- Issue-triage GitHub Actions added (#688): keyword-driven auto-labeller,
stale-bot for `needs-info` issues (14 d → stale → 7 d → close), and a
spam lockdown that auto-closes promotional issues from accounts <30 d
old. All pure GitHub Actions — no third-party services.
- Annotated `TuiPrefs` (#657) and `handoff::THRESHOLDS` (#667) with
`#[allow(dead_code)]` so the deferred APIs don't trip CI's `-D warnings`
flag while their call sites are staged for v0.8.13.
- Removed dead `prefer_handoff` field from `CompactionConfig` — config knob
existed but zero code paths consulted it (#667).
- Removed dead `use_terminal_colors` field from `TuiConfig` — no rendering
+3 -1
View File
@@ -209,7 +209,9 @@ deepseek setup --status # read-only setup status
deepseek setup --tools --plugins # scaffold tool/plugin dirs
deepseek models # list live API models
deepseek sessions # list saved sessions
deepseek resume --last # resume latest session
deepseek resume --last # resume the most recent session
deepseek resume <SESSION_ID> # resume a specific session by UUID
deepseek fork <SESSION_ID> # fork a session at a chosen turn
deepseek serve --http # HTTP/SSE API server
deepseek pr <N> # fetch PR and pre-seed review prompt
deepseek mcp list # list configured MCP servers