hotsheet 0.19.0 → 0.20.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -4
- package/dist/channel.js +130 -2
- package/dist/cli.js +30526 -15028
- package/dist/client/app.global.js +223 -218
- package/dist/client/styles.css +1 -1
- package/package.json +14 -10
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
<br>
|
|
12
12
|
|
|
13
|
-
**Hot Sheet** is a local-first project management tool wired into your AI coding workflow. Create tickets with a bullet-list interface, drag them into priority order, and your AI tools automatically get a structured worklist they can act on. A real PTY-backed terminal lives in the footer drawer — switch to the dashboard view to see every terminal across every project as a tile grid — so you can keep an eye on dev servers, tests, and the AI's own Claude Code session from the same window.
|
|
13
|
+
**Hot Sheet** is a local-first project management tool wired into your AI coding workflow. Create tickets with a bullet-list interface, drag them into priority order, and your AI tools automatically get a structured worklist they can act on. A real PTY-backed terminal lives in the footer drawer — switch to the dashboard view to see every terminal across every project as a tile grid — so you can keep an eye on dev servers, tests, and the AI's own Claude Code session from the same window. Step away, and the **Announcer** narrates what the AI got done while you were gone.
|
|
14
14
|
|
|
15
15
|
No cloud. No logins. No JIRA. Just tickets, terminals, and a tight feedback loop.
|
|
16
16
|
|
|
@@ -183,6 +183,68 @@ Read .hotsheet/worklist.md for current work items.
|
|
|
183
183
|
|
|
184
184
|
Hot Sheet automatically generates skill files for Claude Code (as well as Cursor, GitHub Copilot, and Windsurf) so your AI tool can create tickets directly. Run `/hotsheet` in Claude Code to process the worklist.
|
|
185
185
|
|
|
186
|
+
### Recommended project instructions
|
|
187
|
+
|
|
188
|
+
Hot Sheet works best when your AI assistant follows a few conventions: drive work through Hot Sheet tickets, keep double test coverage, and keep requirements docs in sync. Add these sections to your project's `CLAUDE.md` (Claude Code) — Hot Sheet can do it for you, or copy them by hand.
|
|
189
|
+
|
|
190
|
+
- **Automatic:** when Hot Sheet detects Claude Code in a project, it offers (once per project) to add these sections to your `CLAUDE.md`. Your existing file is preserved — the sections are wrapped in markers so Hot Sheet can keep them up to date without touching anything else, and the test/docs *specifics* are filled in by your assistant for that project.
|
|
191
|
+
- **Manual:** click **Update CLAUDE.md** in **Settings → General** at any time, or copy the blocks below.
|
|
192
|
+
|
|
193
|
+
<details>
|
|
194
|
+
<summary><strong>Ticket-Driven Work</strong></summary>
|
|
195
|
+
|
|
196
|
+
```markdown
|
|
197
|
+
## Ticket-Driven Work
|
|
198
|
+
|
|
199
|
+
When the user gives you work directly (not via the Hot Sheet channel or events), create Hot Sheet tickets before starting implementation — especially for substantial or multi-step work.
|
|
200
|
+
|
|
201
|
+
- **Do create tickets** for: features, bug fixes, refactoring, multi-step tasks, anything changing code. **Don't** for: simple questions, git commits, quick lookups, trivial one-liners. **When in doubt, create them.**
|
|
202
|
+
- Create via the Hot Sheet API (prefer the `hotsheet_*` MCP tools), mark Up Next, then work through them: set status `started` → implement → set `completed` with notes.
|
|
203
|
+
- **Always create follow-up tickets** for incomplete work (unfinished steps, open design questions, known gaps, designed-but-unbuilt features). If it's not in a ticket, it's forgotten.
|
|
204
|
+
- **Incomplete-work checklist** — before marking a ticket `completed`, file follow-ups for any: (1) UI placeholder text ("coming soon"), (2) TODO/FIXME comments, (3) documented-but-unimplemented requirements, (4) empty/stub functions returning mock data.
|
|
205
|
+
- **Use FEEDBACK NEEDED before deferring or asking about follow-ups.** When about to (a) defer a ticket needing more work, (b) ask whether to file follow-ups, or (c) close with a question buried in notes — DON'T. Leave the ticket `started`, add a `FEEDBACK NEEDED:` note (per `.hotsheet/worklist.md`), signal channel done, and wait. It's the only reliable way to surface a question.
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
</details>
|
|
209
|
+
|
|
210
|
+
<details>
|
|
211
|
+
<summary><strong>Testing Philosophy</strong></summary>
|
|
212
|
+
|
|
213
|
+
```markdown
|
|
214
|
+
## Testing Philosophy
|
|
215
|
+
|
|
216
|
+
- **Double coverage**: every feature covered by both unit tests AND E2E tests. Unit = logic in isolation; E2E = real user flows through the running app with minimal mocking.
|
|
217
|
+
- **Unit tests**: Mock external deps (filesystem, network), test real logic.
|
|
218
|
+
- **E2E tests**: As much as possible, use test automation tools to run realistic, user-facing flows. Minimize mocks.
|
|
219
|
+
- **Coverage**: Merge all test coverage (e.g. unit, E2E server, E2E browser) into one report. Low-coverage files should get more of both test types. Aim for 100% coverage of code lines, 100% coverage of branches, and 100% of features described in the requirements documentation.
|
|
220
|
+
- **Manual test plan**: keep a manual test plan doc (e.g. `docs/manual-test-plan.md`) for features that can't be reliably automated. **Keep it up to date** — add such features there; when you add automated coverage for a previously-manual item, remove it and note it in an "Automated Coverage Summary".
|
|
221
|
+
- **Always fix lint and type errors before finishing**: Fix as you go, don't batch.
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
When Hot Sheet adds this section it also scaffolds a self-healing **"this project's test setup"** block: a short prompt that asks your assistant to detect and record the project's actual test runner, file locations, and commands the first time it does test work — so the generic principles get project-specific teeth for any language.
|
|
225
|
+
|
|
226
|
+
</details>
|
|
227
|
+
|
|
228
|
+
<details>
|
|
229
|
+
<summary><strong>Requirements Documentation</strong></summary>
|
|
230
|
+
|
|
231
|
+
```markdown
|
|
232
|
+
## Requirements Documentation
|
|
233
|
+
|
|
234
|
+
Keep human-readable requirements documents as the source of truth for what the project does, and **keep them up to date in the same change as the code** (add/remove/modify a requirement → update its doc). Create new docs for major new functional areas. Cross-reference related docs with relative links.
|
|
235
|
+
|
|
236
|
+
### AI Summaries
|
|
237
|
+
|
|
238
|
+
Maintain two synthesis docs an AI assistant reads at the start of a fresh session — keep them in sync with reality (source doc/code wins on conflict), and prefer small targeted edits over rewrites:
|
|
239
|
+
|
|
240
|
+
- A **codebase map** — directory tree, entry points, data schema, build, tests, settings, and a "where do I look for X" index. Update it in the same change when you add a file or directory, add a route/endpoint, change the schema, add a client module, or add a setting key.
|
|
241
|
+
- A **requirements summary** — a synthesized view of every requirements doc with status markers (e.g. Shipped / Partial / Design only / Deferred). Update it in the same change when you add a requirements doc, ship a design-only feature, or defer/regress a shipped one.
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
</details>
|
|
245
|
+
|
|
246
|
+
See [docs/86-ai-assistant-setup.md](docs/86-ai-assistant-setup.md) for how the auto-install / auto-update mechanism works.
|
|
247
|
+
|
|
186
248
|
### Claude Channel Integration (Experimental)
|
|
187
249
|
|
|
188
250
|
Hot Sheet can push events directly to a running Claude Code session via MCP channels. Enable it in Settings:
|
|
@@ -191,10 +253,10 @@ Hot Sheet can push events directly to a running Claude Code session via MCP chan
|
|
|
191
253
|
- **Auto mode** — double-click the play button to enable automatic mode. Claude is triggered immediately, then continues monitoring for new Up Next items with debounce. Exponential backoff prevents runaway retries.
|
|
192
254
|
- **Auto-prioritize** — when no tickets are flagged as Up Next, Claude automatically evaluates open tickets and picks the most important ones to work on.
|
|
193
255
|
- **Feedback loop** — Claude can request user input by adding notes prefixed with `FEEDBACK NEEDED:` or `IMMEDIATE FEEDBACK NEEDED:`. A rich dialog appears in the UI with inline-response slots between every prompt block, a catch-all field, and file attachment support. Save Draft to come back later (text + attachments survive); Submit re-triggers Claude with your response. Blue dots on project tabs indicate pending feedback.
|
|
194
|
-
- **Custom commands** — create named buttons that send custom prompts to Claude **or run shell commands** directly. Organize into collapsible groups. Toggle between "Claude Code" and "Shell" targets per command. Shell commands execute server-side with stdout/stderr streamed to the commands log in real time.
|
|
256
|
+
- **Custom commands** — create named buttons that send custom prompts to Claude **or run shell commands** directly. Organize into collapsible groups. Toggle between "Claude Code" and "Shell" targets per command. Shell commands execute server-side with stdout/stderr streamed to the commands log in real time. **Long-press** a button for a secondary action (a shell command runs in a fresh terminal; a Claude command files a task ticket), and **hover** any button to see when it last ran.
|
|
195
257
|
- **Permission relay** — when Claude needs tool approval (Bash, Edit, etc.), a full-screen overlay shows the tool name and command preview with Allow/Deny/Dismiss buttons — no need to switch to the terminal. Per-project **allow-rules** can auto-approve specific tool+pattern pairs (e.g. always allow `Bash:npm test`) so trusted commands skip the overlay entirely.
|
|
196
258
|
- **Commands log + embedded terminal** — the footer drawer hosts both a resizable commands log (every trigger, completion, permission request, shell output) AND tabs for any number of project-scoped terminals. Hop between an `npm run dev` terminal, the Claude session, and the audit log without leaving Hot Sheet.
|
|
197
|
-
- **MCP tools** — Claude Code sees Hot Sheet as a connected MCP server with schema-validated tools: `hotsheet_create_ticket`, `hotsheet_update_ticket`, `hotsheet_query_tickets`, `hotsheet_batch`, `hotsheet_signal_done`, `hotsheet_request_feedback`, and 8 more. Tickets, notes, and attachments all round-trip without the AI hand-crafting curl commands.
|
|
259
|
+
- **MCP tools** — Claude Code sees Hot Sheet as a connected MCP server with schema-validated tools: `hotsheet_create_ticket`, `hotsheet_update_ticket`, `hotsheet_query_tickets`, `hotsheet_batch`, `hotsheet_signal_done`, `hotsheet_request_feedback`, `hotsheet_announce`, and 8 more. Tickets, notes, and attachments all round-trip without the AI hand-crafting curl commands.
|
|
198
260
|
- **Status indicator** — shows "Claude working" / "Shell running" / idle in the footer.
|
|
199
261
|
|
|
200
262
|
Requires Claude Code v2.1.80+ with channel support. See [docs/12-claude-channel.md](docs/12-claude-channel.md) for setup details.
|
|
@@ -203,6 +265,23 @@ Requires Claude Code v2.1.80+ with channel support. See [docs/12-claude-channel.
|
|
|
203
265
|
<img src="docs/demo-9.png" alt="Claude Channel integration with play button, custom command buttons, and AI-driven workflow" width="900">
|
|
204
266
|
</p>
|
|
205
267
|
|
|
268
|
+
### Announcer — narrated playback of project work (Beta)
|
|
269
|
+
|
|
270
|
+
Step away while Claude works, and the **Announcer** catches you up. It turns completion notes, the command log, and Claude Code's own telemetry stream into a short spoken-and-visual digest — a draggable, resizable picture-in-picture transcript that reads each update aloud, emphasizes the key phrases, and shows the actual before/after code diff for the change it's describing.
|
|
271
|
+
|
|
272
|
+
- **After-the-fact digest** — click **Listen** to hear everything that happened since you last checked in, narrated in order. The PIP shows the running transcript with playback controls (play/pause, previous, next, speed) and tier-1 emphasis on the phrases that matter.
|
|
273
|
+
- **Live mode** — narrates work as it happens, coalescing bursts of activity into coherent entries and learning from the ones you skip. It's **off unless you're listening** — a client-renewed lease gates generation so it never spends your key in the background, with a per-project call budget on top.
|
|
274
|
+
- **Cross-project** — an "All Projects" context interleaves every enabled project's reel chronologically, each entry tagged with a project chip and prefixed with its project name when spoken.
|
|
275
|
+
- **Spoken permission checks** — hear "Permission needed in *Project*: …" read aloud when Claude needs tool approval, even with no PIP open and no API key required.
|
|
276
|
+
- **Bring your own model — or none** — summarize with your Anthropic key, **on-device with Apple Foundation Models** (macOS 26, free and fully private, no key), or a local **Ollama / OpenAI-compatible** endpoint. Playback uses the built-in OS/browser voice by default.
|
|
277
|
+
- **Code-diff visuals** — the working agent can hand the Announcer the exact before/after through the `hotsheet_announce` MCP tool, rendered inline in the PIP next to the narration.
|
|
278
|
+
|
|
279
|
+
API keys are managed once in **Settings → API Keys** — a machine-global registry of named keys stored in the OS keychain, selected by name per project so you never paste a secret twice. Enable narration in **Settings → Announcer**.
|
|
280
|
+
|
|
281
|
+
<p align="center">
|
|
282
|
+
<img src="docs/demo-14.png" alt="Announcer transcript picture-in-picture narrating recent work over the ticket board, with emphasized phrases and an inline before/after code diff" width="900">
|
|
283
|
+
</p>
|
|
284
|
+
|
|
206
285
|
### Telemetry & Cost Tracking
|
|
207
286
|
|
|
208
287
|
**On by default** (HS-8684 — opt out per project via Settings → Telemetry). Hot Sheet stamps Claude Code's spawn env so its OpenTelemetry exporter posts cost / token / latency events back to a localhost-bound endpoint. The data drives several surfaces:
|
|
@@ -213,7 +292,7 @@ Requires Claude Code v2.1.80+ with channel support. See [docs/12-claude-channel.
|
|
|
213
292
|
- **Per-ticket Claude usage** — when you trigger Claude via the channel with an active ticket selected, Hot Sheet prepends an invisible `<!-- hotsheet:ticket=HS-NNNN -->` marker to the prompt so the cost / tokens / wall-clock from that work attribute back to the ticket and appear as a "Claude usage on this ticket" block in the detail panel.
|
|
214
293
|
- **Beta enhanced tracing** — separate toggle wires `CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1` so each prompt's drilldown switches from a flat event timeline to a parent-child span tree with an inline waterfall chart. New `claude` sessions started after the toggle begin capturing spans.
|
|
215
294
|
|
|
216
|
-
Security model: localhost-bound OTLP receiver + `hotsheet_project` resource-attribute filter — foreign OTLP traffic from other tools on the same machine can't pollute Hot Sheet's tables even if it tries. 30-day default
|
|
295
|
+
Security model: localhost-bound OTLP receiver + `hotsheet_project` resource-attribute filter — foreign OTLP traffic from other tools on the same machine can't pollute Hot Sheet's tables even if it tries. Telemetry is stored per-project with a configurable retention window (30-day default) enforced by a periodic sweep with per-table windows and a row cap, so the database can't grow without bound; **Clear telemetry data** in Settings wipes the project's rows on demand.
|
|
217
296
|
|
|
218
297
|
<p align="center">
|
|
219
298
|
<img src="docs/demo-13.png" alt="Cross-project telemetry stats page with cost-over-time chart, cost-by-project table, model donut, and hourly activity heatmap" width="900">
|
package/dist/channel.js
CHANGED
|
@@ -10283,6 +10283,19 @@ import { z as z3 } from "zod";
|
|
|
10283
10283
|
|
|
10284
10284
|
// src/routes/validation.ts
|
|
10285
10285
|
import { z as z2 } from "zod";
|
|
10286
|
+
|
|
10287
|
+
// src/announcer/models.ts
|
|
10288
|
+
var APPLE_FOUNDATION_MODEL_ID = "apple-foundation";
|
|
10289
|
+
var LOCAL_MODEL_ID = "local";
|
|
10290
|
+
var ANNOUNCER_PRICING = {
|
|
10291
|
+
[APPLE_FOUNDATION_MODEL_ID]: { inputPerMTok: 0, outputPerMTok: 0 },
|
|
10292
|
+
[LOCAL_MODEL_ID]: { inputPerMTok: 0, outputPerMTok: 0 },
|
|
10293
|
+
"claude-haiku-4-5": { inputPerMTok: 1, outputPerMTok: 5 },
|
|
10294
|
+
"claude-sonnet-4-6": { inputPerMTok: 3, outputPerMTok: 15 },
|
|
10295
|
+
"claude-opus-4-8": { inputPerMTok: 5, outputPerMTok: 25 }
|
|
10296
|
+
};
|
|
10297
|
+
|
|
10298
|
+
// src/routes/validation.ts
|
|
10286
10299
|
var TicketPrioritySchema = z2.enum(["highest", "high", "default", "low", "lowest"]);
|
|
10287
10300
|
var TicketStatusSchema = z2.enum(["not_started", "started", "completed", "verified", "backlog", "archive", "deleted"]);
|
|
10288
10301
|
var SortBySchema = z2.enum(["created", "modified", "priority", "category", "status"]);
|
|
@@ -10422,6 +10435,16 @@ var DashboardConfigSchema = z2.object({
|
|
|
10422
10435
|
// made after HS-8406 landed could persist across relaunches.
|
|
10423
10436
|
activeVisibilityGroupingIdByScope: z2.record(z2.string(), z2.string()).optional()
|
|
10424
10437
|
}).strict();
|
|
10438
|
+
var KeyTypeSchema = z2.enum(["anthropic_api_key"]);
|
|
10439
|
+
var SecretKeyMetaSchema = z2.object({
|
|
10440
|
+
id: z2.string(),
|
|
10441
|
+
type: KeyTypeSchema,
|
|
10442
|
+
name: z2.string(),
|
|
10443
|
+
// HS-8760 — provenance shown in the API Keys row ("Created/Updated …").
|
|
10444
|
+
// Optional for back-compat with keys created before HS-8760.
|
|
10445
|
+
created_at: z2.string().optional(),
|
|
10446
|
+
updated_at: z2.string().optional()
|
|
10447
|
+
});
|
|
10425
10448
|
var GlobalConfigSchema = z2.object({
|
|
10426
10449
|
channelEnabled: z2.boolean().optional(),
|
|
10427
10450
|
shareTotalSeconds: z2.number().optional(),
|
|
@@ -10434,7 +10457,65 @@ var GlobalConfigSchema = z2.object({
|
|
|
10434
10457
|
terminalWebglOptOut: z2.boolean().optional(),
|
|
10435
10458
|
// HS-8497 — billing model for telemetry cost display. See
|
|
10436
10459
|
// `global-config.ts` for the contract.
|
|
10437
|
-
telemetryCostMode: z2.enum(["api", "subscription"]).optional()
|
|
10460
|
+
telemetryCostMode: z2.enum(["api", "subscription"]).optional(),
|
|
10461
|
+
// HS-8751 — global API-key registry (metadata only; values in the keychain).
|
|
10462
|
+
keys: z2.array(SecretKeyMetaSchema).optional(),
|
|
10463
|
+
// HS-8754 — Announcer playback speed multiplier (1 = normal). Global because
|
|
10464
|
+
// it's a listening preference, not project-specific. Clamped 0.5×–2×.
|
|
10465
|
+
announcerSpeechRate: z2.number().min(0.5).max(2).optional(),
|
|
10466
|
+
// HS-8764 — Announcer summarization model. Global; defaults to the cheapest
|
|
10467
|
+
// (Haiku) when unset. See `src/announcer/models.ts`. HS-8853 — the Anthropic
|
|
10468
|
+
// list is now discovered dynamically from the user's key, so this accepts any
|
|
10469
|
+
// `claude-*` id (not just the static set) plus the two on-device pseudo-ids.
|
|
10470
|
+
announcerModel: z2.string().refine(
|
|
10471
|
+
(v) => v === APPLE_FOUNDATION_MODEL_ID || v === LOCAL_MODEL_ID || v.startsWith("claude-"),
|
|
10472
|
+
{ message: "must be an on-device provider id or a claude-* model id" }
|
|
10473
|
+
).optional(),
|
|
10474
|
+
// HS-8792 — local-provider config (used only when `announcerModel === 'local'`).
|
|
10475
|
+
// `Endpoint` is the OpenAI-compatible base URL (default `http://localhost:11434/v1`);
|
|
10476
|
+
// `Model` is the concrete local model name (e.g. `llama3.1`). Both global.
|
|
10477
|
+
announcerLocalEndpoint: z2.string().optional(),
|
|
10478
|
+
announcerLocalModel: z2.string().optional(),
|
|
10479
|
+
// HS-8891 — optional fallback model used ONLY when the primary is Apple
|
|
10480
|
+
// Foundation Models and it fails at inference (the HS-8883 "code 4" class). A
|
|
10481
|
+
// non-apple id: a `claude-*` model (cloud backup, spends on the user's key) or
|
|
10482
|
+
// the local pseudo-id. Empty string / unset = no fallback (Apple failure → no
|
|
10483
|
+
// narration, the pre-HS-8891 behavior). The auto-selected-on-device fallback
|
|
10484
|
+
// (HS-8805) is separate and unaffected.
|
|
10485
|
+
announcerFallbackModel: z2.string().refine(
|
|
10486
|
+
(v) => v === "" || v === LOCAL_MODEL_ID || v.startsWith("claude-"),
|
|
10487
|
+
{ message: "must be empty, the local provider id, or a claude-* model id" }
|
|
10488
|
+
).optional(),
|
|
10489
|
+
// HS-8781 — verbally announce permission checks (TTS only, no API cost).
|
|
10490
|
+
// Global; default ON, so `undefined`/unset is treated as enabled by the
|
|
10491
|
+
// client (`announcerSpeakPermissions !== false`).
|
|
10492
|
+
announcerSpeakPermissions: z2.boolean().optional(),
|
|
10493
|
+
// HS-8874 — one-time marker that the per-project telemetry migration
|
|
10494
|
+
// (`migratePerProjectTelemetry`) has run. Set after a successful, non-
|
|
10495
|
+
// destructive copy of legacy launch-default telemetry rows into each row's
|
|
10496
|
+
// owning project DB / the central store. Skipped on subsequent startups.
|
|
10497
|
+
telemetryMigratedV1: z2.boolean().optional(),
|
|
10498
|
+
// HS-8874 (migration efficiency) — per-source-DB resumability for the
|
|
10499
|
+
// telemetry migration. Each source project dir is appended here once all its
|
|
10500
|
+
// foreign rows have been copied, so a crash/quit mid-migration resumes at the
|
|
10501
|
+
// first incomplete DB instead of restarting from zero (the boot-loop the
|
|
10502
|
+
// end-only `telemetryMigratedV1` flag caused). Cleared when migration completes.
|
|
10503
|
+
telemetryMigrationV1DoneDirs: z2.array(z2.string()).optional(),
|
|
10504
|
+
// HS-8877 — retention window (days) for the centralized non-project telemetry
|
|
10505
|
+
// store (`~/.hotsheet/telemetry`). Projects have a per-project
|
|
10506
|
+
// `telemetry_retention_days`; central isn't a project, so its sweep window
|
|
10507
|
+
// lives here. Unset → the §67.6 default (30 days). `0` keeps central forever.
|
|
10508
|
+
centralTelemetryRetentionDays: z2.number().int().min(0).optional(),
|
|
10509
|
+
// HS-8890 (§85.2.2) — retention window (days) for `otel_spans` in the central
|
|
10510
|
+
// store. Spans (§68 enhanced tracing) are high-volume, so they age out faster
|
|
10511
|
+
// than metrics/events: unset → the §85 default of 7 days (vs 30 for
|
|
10512
|
+
// metrics/events via `centralTelemetryRetentionDays`); `0` keeps spans forever.
|
|
10513
|
+
centralSpanRetentionDays: z2.number().int().min(0).optional(),
|
|
10514
|
+
// HS-8884 — last time a `VACUUM FULL` reclaim ran per telemetry DB dir
|
|
10515
|
+
// (`<dataDir>/db` or the central store), keyed by that dir's absolute path →
|
|
10516
|
+
// ISO timestamp. Throttles the heavy, exclusive-lock full reclaim to at most
|
|
10517
|
+
// once per `FULL_VACUUM_THROTTLE_DAYS`; routine plain VACUUMs aren't tracked.
|
|
10518
|
+
telemetryVacuumFullAt: z2.record(z2.string(), z2.string()).optional()
|
|
10438
10519
|
}).strict();
|
|
10439
10520
|
var PluginActionSchema = z2.object({
|
|
10440
10521
|
actionId: z2.string(),
|
|
@@ -10577,6 +10658,15 @@ var QueryTicketsInputSchema = z3.object({
|
|
|
10577
10658
|
required_tag: z3.string().optional().describe("When set, only tickets carrying this tag are included"),
|
|
10578
10659
|
include_archived: z3.boolean().optional()
|
|
10579
10660
|
});
|
|
10661
|
+
var AnnounceInputSchema = z3.object({
|
|
10662
|
+
title: z3.string().min(1).describe('A few words naming the moment (e.g. "Fixed the data-loss bug").'),
|
|
10663
|
+
highlight: z3.string().min(1).describe("One or two short sentences of natural spoken English to read aloud \u2014 what happened and why it matters."),
|
|
10664
|
+
diff: z3.object({
|
|
10665
|
+
oldStr: z3.string().describe("The code BEFORE the change (the focused snippet you changed, not the whole file)."),
|
|
10666
|
+
newStr: z3.string().describe("The code AFTER the change."),
|
|
10667
|
+
filePath: z3.string().optional().describe("Optional file path shown as the diff header.")
|
|
10668
|
+
}).optional().describe("Optional code diff to display with this highlight \u2014 supply the before/after of the focused change you want to show off.")
|
|
10669
|
+
});
|
|
10580
10670
|
async function dispatchUpdateTicket(args2, settings, fetchFn) {
|
|
10581
10671
|
const parsed = UpdateTicketInputSchema.safeParse(args2);
|
|
10582
10672
|
if (!parsed.success) {
|
|
@@ -10707,6 +10797,13 @@ async function dispatchDeleteNote(args2, settings, fetchFn) {
|
|
|
10707
10797
|
const { ticket_id, note_id } = parsed.data;
|
|
10708
10798
|
return await proxyRequest(settings, `/api/tickets/${String(ticket_id)}/notes/${encodeURIComponent(note_id)}`, { method: "DELETE" }, fetchFn);
|
|
10709
10799
|
}
|
|
10800
|
+
async function dispatchAnnounce(args2, settings, fetchFn) {
|
|
10801
|
+
const parsed = AnnounceInputSchema.safeParse(args2);
|
|
10802
|
+
if (!parsed.success) {
|
|
10803
|
+
return errorResult(`hotsheet_announce \u2014 validation failed: ${parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ")}`);
|
|
10804
|
+
}
|
|
10805
|
+
return await proxyRequest(settings, "/api/announcer/announce", { method: "POST", body: parsed.data }, fetchFn);
|
|
10806
|
+
}
|
|
10710
10807
|
async function dispatchQueryTickets(args2, settings, fetchFn) {
|
|
10711
10808
|
const parsed = QueryTicketsInputSchema.safeParse(args2);
|
|
10712
10809
|
if (!parsed.success) {
|
|
@@ -10799,6 +10896,13 @@ var TOOLS = [
|
|
|
10799
10896
|
description: 'Run a custom-view-style query: combine field/operator/value conditions via AND (logic="all") or OR (logic="any"), with optional sort_by / sort_dir / required_tag / include_archived. Returns the matching tickets. For agents that need to dig deeper than the worklist provides.',
|
|
10800
10897
|
inputSchema: QueryTicketsInputSchema,
|
|
10801
10898
|
call: dispatchQueryTickets
|
|
10899
|
+
},
|
|
10900
|
+
// HS-8771 — hybrid Announcer generation (§80).
|
|
10901
|
+
{
|
|
10902
|
+
name: "hotsheet_announce",
|
|
10903
|
+
description: `Push a curated Announcer highlight for a genuinely notable moment ("fixed a data-loss bug", "shipped the export"). It pre-empts the derived narration queue with a low-latency, high-intent entry (no AI summarization). Use sparingly, only for moments worth interrupting for. No-op if the project hasn't enabled the Announcer.`,
|
|
10904
|
+
inputSchema: AnnounceInputSchema,
|
|
10905
|
+
call: dispatchAnnounce
|
|
10802
10906
|
}
|
|
10803
10907
|
];
|
|
10804
10908
|
function listTools() {
|
|
@@ -10964,6 +11068,16 @@ var TicketSchema = z6.object({
|
|
|
10964
11068
|
last_read_at: z6.string().nullable()
|
|
10965
11069
|
});
|
|
10966
11070
|
var TagsArraySchema = z6.array(z6.string());
|
|
11071
|
+
var EmphasisArraySchema = z6.array(z6.string());
|
|
11072
|
+
var DiffVisualSchema = z6.object({
|
|
11073
|
+
type: z6.literal("diff"),
|
|
11074
|
+
oldStr: z6.string(),
|
|
11075
|
+
newStr: z6.string(),
|
|
11076
|
+
filePath: z6.string().nullable().default(null),
|
|
11077
|
+
replaceAll: z6.boolean().default(false)
|
|
11078
|
+
});
|
|
11079
|
+
var VisualSchema = z6.discriminatedUnion("type", [DiffVisualSchema]);
|
|
11080
|
+
var VisualsArraySchema = z6.array(VisualSchema);
|
|
10967
11081
|
var AutoContextEntrySchema = z6.object({
|
|
10968
11082
|
type: z6.enum(["category", "tag"]),
|
|
10969
11083
|
key: z6.string(),
|
|
@@ -11039,6 +11153,20 @@ var PermissionResultBodySchema = z6.object({
|
|
|
11039
11153
|
var GithubCommentsArraySchema = z6.array(z6.object({
|
|
11040
11154
|
body_html: z6.string().optional()
|
|
11041
11155
|
}).loose());
|
|
11156
|
+
var CustomViewConditionSchema = z6.object({
|
|
11157
|
+
field: z6.string(),
|
|
11158
|
+
operator: z6.string(),
|
|
11159
|
+
value: z6.string()
|
|
11160
|
+
}).loose();
|
|
11161
|
+
var CustomViewSchema = z6.object({
|
|
11162
|
+
id: z6.string(),
|
|
11163
|
+
name: z6.string(),
|
|
11164
|
+
tag: z6.string().optional(),
|
|
11165
|
+
includeArchived: z6.boolean().optional(),
|
|
11166
|
+
logic: z6.enum(["all", "any"]).default("all"),
|
|
11167
|
+
conditions: z6.array(CustomViewConditionSchema).default([])
|
|
11168
|
+
}).loose();
|
|
11169
|
+
var CustomViewArraySchema = z6.array(CustomViewSchema);
|
|
11042
11170
|
|
|
11043
11171
|
// src/channel-config.ts
|
|
11044
11172
|
var McpConfigSchema = z7.object({
|
|
@@ -11279,7 +11407,7 @@ function installStdioDisconnectHandler(opts) {
|
|
|
11279
11407
|
}
|
|
11280
11408
|
|
|
11281
11409
|
// src/channel.ts
|
|
11282
|
-
var CHANNEL_VERSION =
|
|
11410
|
+
var CHANNEL_VERSION = 11;
|
|
11283
11411
|
var dataDir = ".hotsheet";
|
|
11284
11412
|
var args = process.argv.slice(2);
|
|
11285
11413
|
for (let i = 0; i < args.length; i++) {
|