Skip to content

[AI-1569] Tombstone the retired agent verb: rename pointer to kcap daemon, exit 2 - #390

Merged
realtonyyoung merged 2 commits into
mainfrom
tonyyoung/ai-1569-agent-tombstone
Jul 29, 2026
Merged

realtonyyoung merged 2 commits into
mainfrom
tonyyoung/ai-1569-agent-tombstone

Conversation

@realtonyyoung

Copy link
Copy Markdown
Collaborator

Problem

Linear AI-1569 — the daemon verb was renamed agent → daemon in May 2026 (c6f1fd5), but the dead verb lives on in channels that can never be fully swept: old session transcripts resurfaced by recap/search, pre-fix server strings on not-yet-rolled-out tenants, worktrees branched before the docs fixes, notes, and agent memories. Each one funnels a user or coding agent into running kcap agent, and the generic Unknown command: agent reply names nothing to run instead — the AI-1489/AI-1559 misdiagnosis loop (healthy daemon reads as dead).

Fix

kcap agent … — including agent start and agent --help — now answers:

Unknown command: agent — the daemon verb was renamed to 'daemon'.
Run `kcap daemon start|stop|status`, or `kcap --help`.

with exit 2, matching the removed cursor-import precedent. Placed before per-command help and before server-config resolution, so it works logged-out and offline. Deliberately not an alias — the verb stays dead; stale channels self-correct at the point of execution instead of fossilizing.

The message and comments avoid the literal retired phrase, so the repo scan landing in the AI-1567 PR stays green regardless of merge order.

Verification

  • RetiredAgentVerbTests (integration, spawns the built binary): 3/3 across agent / agent start / agent --help — pins stderr content and exit 2.
  • Manual smoke of the built binary reproduces the exact two lines above with exit=2.
  • scripts/check-linear-ids.sh clean (no issue ids in .cs).

Related: kcap-server AI-1559 (#1210), AI-1568 (kcap-server #1213), AI-1567 (skill docs — separate PR).

🤖 Generated with Claude Code

…exit 2

The daemon verb was renamed in May 2026, but the dead verb lives on in
old transcripts, docs, memories, and habits — and the generic "Unknown
command: agent" reply is how a healthy daemon reads as dead mid-
diagnosis (the message names nothing to run instead).

`kcap agent …` — including `agent start` and `agent --help` — now
answers with a rename pointer and exits 2, matching the removed
cursor-import precedent. Placed before per-command help and before any
server-config resolution, so it works logged-out and offline.
Deliberately NOT an alias: the verb stays dead, so stale channels
self-correct at the point of execution instead of fossilizing.

The message avoids the literal retired phrase so the repo scan landing
separately stays green regardless of merge order.

Tests: RetiredAgentVerbTests (integration, spawns the built binary)
3/3 across the three arg forms.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@linear-code

linear-code Bot commented Jul 29, 2026

Copy link
Copy Markdown

AI-1569

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Tombstone retired agent verb with daemon migration guidance

🐞 Bug fix 🧪 Tests 🕐 10-20 Minutes

Grey Divider

AI Description

• Adds targeted guidance when users invoke the retired agent verb.
• Preserves removal semantics by returning exit code 2 instead of aliasing.
• Covers bare, subcommand, and help invocations through binary integration tests.
Diagram

graph TD
    A["CLI arguments"] --> B["Resolve server URL"] --> C{"Agent verb?"} -->|Yes| D["Rename guidance"] --> E["Exit code 2"]
    C -->|No| F["Help or dispatch"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Retain agent as an alias
  • ➕ Avoids breaking stale scripts and remembered commands.
  • ➕ Provides a seamless migration path for existing users.
  • ➖ Keeps the retired vocabulary operational indefinitely.
  • ➖ Prevents stale transcripts and documentation from self-correcting.
  • ➖ Could conceal incorrect diagnostics by silently accepting obsolete commands.
2. Register a dedicated retired command handler
  • ➕ Could encapsulate migration messaging within the normal command framework.
  • ➕ May simplify adding tombstones for additional retired verbs.
  • ➖ May allow per-command help or configuration checks to intercept the invocation.
  • ➖ Adds abstraction for a single targeted compatibility diagnostic.
  • ➖ Could blur the distinction between a supported command and a tombstone.

Recommendation: Keep the targeted top-level tombstone. It catches agent, subcommands, and help requests consistently while preserving the verb's removal through exit code 2; an alias would prolong stale usage, and a full command handler adds unnecessary structure.

Files changed (2) +68 / -0

Bug fix (1) +11 / -0
Program.csIntercept the retired agent verb with daemon guidance +11/-0

Intercept the retired agent verb with daemon guidance

• Adds a top-level command guard that directs obsolete 'agent' invocations to 'kcap daemon start|stop|status'. The guard runs before per-command help and normal dispatch, writes to stderr, and returns exit code 2 without creating an alias.

src/Capacitor.Cli/Program.cs

Tests (1) +57 / -0
RetiredAgentVerbTests.csVerify retired agent behavior through the built CLI +57/-0

Verify retired agent behavior through the built CLI

• Adds integration coverage for 'agent', 'agent start', and 'agent --help' by spawning the platform-specific built binary. The test pins exit code 2 and the daemon migration guidance written to stderr.

test/Capacitor.Cli.Tests.Integration/RetiredAgentVerbTests.cs

@qodo-code-review

qodo-code-review Bot commented Jul 29, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (0)

Context used
⚠️ Tickets: not configured — ticket URL found in PR but could not be fetched — check ticket provider credentials

Grey Divider


Action required

1. agent comments duplicate rationale ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
The production and test comments repeat extensive historical and behavioral rationale instead of
concisely explaining the tombstone. This violates the requirement that source comments remain
necessary and concise.
Code

src/Capacitor.Cli/Program.cs[R82-85]

+// `agent` was the daemon verb until May 2026; the rename left it alive in old transcripts,
+// docs, and habits, and the bare unknown-command error sent people hunting for a daemon that
+// was never down. Answer it with a pointer instead — deliberately NOT an alias: the verb
+// stays dead (exit 2, matching the removed cursor import command).
Evidence
PR Compliance ID 3 requires comments to be concise and necessary. The production comment uses four
lines to explain history, user behavior, alias policy, and exit-code precedent, while the test
summary repeats the same rationale across six lines.

CLAUDE.md: Keep Code Comments Concise and Free of Linear Issue Numbers
src/Capacitor.Cli/Program.cs[82-85]
test/Capacitor.Cli.Tests.Integration/RetiredAgentVerbTests.cs[5-11]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new comments contain verbose historical rationale that duplicates the implementation and tests.

## Issue Context
Keep only a short explanation that `agent` is intentionally rejected rather than retained as an alias. Do not add a Linear issue identifier.

## Fix Focus Areas
- src/Capacitor.Cli/Program.cs[82-85]
- test/Capacitor.Cli.Tests.Integration/RetiredAgentVerbTests.cs[5-11]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. README omits agent tombstone ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
The PR changes the user-visible behavior and exit status of kcap agent without updating README.md.
Users consulting the Getting started and CLI command sections will not learn that the retired verb
points to kcap daemon and exits with status 2.
Code

src/Capacitor.Cli/Program.cs[R86-90]

+if (command is "agent") {
+    Console.Error.WriteLine("Unknown command: agent — the daemon verb was renamed to 'daemon'.");
+    Console.Error.WriteLine("Run `kcap daemon start|stop|status`, or `kcap --help`.");
+
+    return 2;
Evidence
PR Compliance ID 5 requires every user-facing CLI behavior change to update both README areas. The
added dispatch branch changes kcap agent, while the current Getting started and daemon command
documentation contain no corresponding migration or tombstone guidance.

CLAUDE.md: Synchronize README Documentation with User-Facing CLI Changes
src/Capacitor.Cli/Program.cs[86-90]
README.md[89-104]
README.md[585-599]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
README.md does not document the new `kcap agent` tombstone behavior.

## Issue Context
Document that `agent` is retired rather than an alias, points users to `kcap daemon start|stop|status`, and exits with status 2. Compliance requires coverage in both Getting started and the relevant CLI command section.

## Fix Focus Areas
- README.md[89-104]
- README.md[585-599]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Tombstone runs after startup ✓ Resolved 🐞 Bug ≡ Correctness
Description
The agent branch executes only after profile/server resolution and update-check startup, so stale
invocations can incur Git/config work and conditionally print unrelated warnings or update output
before the rename pointer. This breaks the intended deterministic offline early exit.
Code

src/Capacitor.Cli/Program.cs[86]

+if (command is "agent") {
Evidence
The new branch is at Program.cs lines 86-90, but Program.cs lines 59-74 have already resolved
configuration and launched the update check. ResolveServerUrl performs config and Git discovery and
can emit warnings, while config migration and update checking can also write to stderr, making the
tombstone response conditional on unrelated local state.

src/Capacitor.Cli/Program.cs[59-90]
src/Capacitor.Cli.Core/Config/AppConfig.cs[93-158]
src/Capacitor.Cli.Core/Config/AppConfig.cs[270-312]
src/Capacitor.Cli/Commands/UpdateCommand.cs[126-145]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The retired `agent` command is handled after server/profile resolution and update-check startup. Handle it immediately after extracting the command so it cannot perform unrelated initialization, alter stderr, or incur avoidable delays.

## Issue Context
`AppConfig.ResolveServerUrl` may load or migrate configuration, invoke Git discovery, and emit warnings. The update-check task may also emit a cached update notice to stderr.

## Fix Focus Areas
- src/Capacitor.Cli/Program.cs[18-18]
- src/Capacitor.Cli/Program.cs[59-91]
- test/Capacitor.Cli.Tests.Integration/RetiredAgentVerbTests.cs[28-43]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

Comment thread src/Capacitor.Cli/Program.cs Outdated
Comment thread src/Capacitor.Cli/Program.cs Outdated
Comment thread src/Capacitor.Cli/Program.cs Outdated
… concise comments

- The agent check moves to immediately after command extraction —
  before ResolveServerUrl's config/git discovery and the update-check
  spawn — so the dead verb exits fast, offline, and deterministically
  (the prior placement paid config resolution first and could
  interleave unrelated stderr).
- README documents the tombstone in the daemon section and the setup
  wizard step.
- Production and test comments trimmed per the concise-comment rule.

Tests: integration 3/3; smoke shows the two pointer lines with exit 2.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@realtonyyoung
realtonyyoung merged commit 11c625d into main Jul 29, 2026
14 of 16 checks passed
@realtonyyoung
realtonyyoung deleted the tonyyoung/ai-1569-agent-tombstone branch July 29, 2026 03:46
alexeyzimarev added a commit that referenced this pull request Jul 29, 2026
Per the decision to keep `kcap agent` as the coding-agent group, drops
RetiredVerbScanTests (AI-1567), which banned the literal string "kcap agent"
from all shipped text under kcap/, src/ and npm/ and is what failed CI on both
platforms.

Addresses the review findings on this PR:

- The dispatch test did not prove dispatch. In a config-less environment every
  non-help case exited 1 at the missing-server gate and `--help` returned from
  the global help path, so nothing pinned that AgentCommand was reached — another
  pre-dispatch guard would have passed it. Each case now asserts a string only
  AgentCommand emits, and points `ls` at a daemon name that cannot exist so the
  handler's own output is deterministic.

- Windows bypassed the daemon signpost. NotSupportedOnWindows returned before the
  subcommand switch, so `kcap agent status` reported that coding agents are
  unsupported instead of pointing at `kcap daemon status`, which Windows does
  support. The signpost now runs ahead of the platform guard.

- The group sat behind the server-config gate, which made the signpost
  unreachable offline. `agent` joins offlineCommands and `start` — the only
  subcommand that needs a server for the daemon to record to — reports the
  missing server itself. ls/attach/stop only ever talk to the local socket.

Two defects the rewritten test then caught in the group itself:

- Any argv[1] was treated as a subcommand, so `kcap agent --daemon dev` failed
  with "unknown subcommand '--daemon'" instead of listing that daemon's agents.
  A leading flag is now an `ls` option.

- `--no-update-check` is global and left in argv by Program.cs, so strict
  parsing read it as a subcommand and, worse, as a vendor name for `start`.
  Global flags are dropped before the split.

Closes #391
AI-1570
Reverts the CLI behaviour of #390 (AI-1569) and the text ban from #389 (AI-1567).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
alexeyzimarev added a commit that referenced this pull request Jul 29, 2026
…ombstone (#392)

* Restore the `kcap agent` command group shadowed by the retired-verb tombstone

#390 added a `command is "agent"` guard at the top of Program.cs that exits 2
with a pointer to `kcap daemon`. #383 added the `kcap agent start|ls|stop|attach`
group at `case "agent":` in the switch below it. They merged without conflict —
different regions of the file — and the guard wins, so every `kcap agent`
subcommand on main answers "Unknown command: agent" and exits 2.

Neither side's tests caught it: #390's assert the tombstone fires (it does), and
#383's exercise the parsers and daemon handlers directly, never through
Program.cs. AgentVerbDispatchTests now spawns the real binary and pins that the
group is reachable, which is the gap that let this through.

The daemon signpost is kept where it doesn't collide: `kcap agent status`,
`restart`, `logs`, `doctor`, and `service` only ever meant the daemon, so they
answer with a pointer to `kcap daemon <verb>`. `start` and `stop` belong to both
groups and dispatch to the agent group.

Note this is reachable only with a server configured — the `agent` group resolves
config before dispatch, unlike the pre-config tombstone it replaces.

Closes #391
AI-1570
Reverts the CLI behaviour of #390 (AI-1569).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Remove the retired-verb text ban; fix dispatch, Windows and offline gaps

Per the decision to keep `kcap agent` as the coding-agent group, drops
RetiredVerbScanTests (AI-1567), which banned the literal string "kcap agent"
from all shipped text under kcap/, src/ and npm/ and is what failed CI on both
platforms.

Addresses the review findings on this PR:

- The dispatch test did not prove dispatch. In a config-less environment every
  non-help case exited 1 at the missing-server gate and `--help` returned from
  the global help path, so nothing pinned that AgentCommand was reached — another
  pre-dispatch guard would have passed it. Each case now asserts a string only
  AgentCommand emits, and points `ls` at a daemon name that cannot exist so the
  handler's own output is deterministic.

- Windows bypassed the daemon signpost. NotSupportedOnWindows returned before the
  subcommand switch, so `kcap agent status` reported that coding agents are
  unsupported instead of pointing at `kcap daemon status`, which Windows does
  support. The signpost now runs ahead of the platform guard.

- The group sat behind the server-config gate, which made the signpost
  unreachable offline. `agent` joins offlineCommands and `start` — the only
  subcommand that needs a server for the daemon to record to — reports the
  missing server itself. ls/attach/stop only ever talk to the local socket.

Two defects the rewritten test then caught in the group itself:

- Any argv[1] was treated as a subcommand, so `kcap agent --daemon dev` failed
  with "unknown subcommand '--daemon'" instead of listing that daemon's agents.
  A leading flag is now an `ls` option.

- `--no-update-check` is global and left in argv by Program.cs, so strict
  parsing read it as a subcommand and, worse, as a vendor name for `start`.
  Global flags are dropped before the split.

Closes #391
AI-1570
Reverts the CLI behaviour of #390 (AI-1569) and the text ban from #389 (AI-1567).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant