Skip to content

[AI-1530] Ship the Capacitor guided-tour skill and point setup at it#369

Open
stktung wants to merge 29 commits into
mainfrom
worktree-add-guided-tour-skill
Open

[AI-1530] Ship the Capacitor guided-tour skill and point setup at it#369
stktung wants to merge 29 commits into
mainfrom
worktree-add-guided-tour-skill

Conversation

@stktung

@stktung stktung commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Closes #368 · AI-1530

What

Ships the Capacitor guided-tour skill in the kcap plugin, and gives it a discovery path from kcap setup.

A user who finishes kcap setup is recording and has no idea what that buys them. Every skill we ship today assumes the user already knows what Capacitor does and which surface they want. guided-tour is the onboarding path: it shows the team's recorded sessions, spend and errors, then offers per-use-case tutorial tours (session recall, evals, PR review, analytics) — and handles the missing pieces, offering to install kcap when it isn't set up and to import history when the user has no sessions.

Spec: docs/superpowers/specs/2026-07-27-guided-tour-skill-design.md

Changes

File Change
kcap/skills/guided-tour/SKILL.md new skill
src/Capacitor.Cli.Core/AgentsSkillsInstaller.cs SourceNames += guided-tour — reaches Codex/Cursor/Kiro/Antigravity via ~/.agents/skills/kcap-guided-tour/
src/Capacitor.Cli/Commands/SetupCommand.cs closing call-to-action panel, wording pinned in an internal const
src/Capacitor.Cli/Commands/CodingAgentsStep.cs Step-4's installed-skills line now derives from SourceNames instead of a hand-maintained copy (which had already drifted — it printed review-flows unprefixed)
kcap/.claude-plugin/plugin.json 1.7.2 → 1.8.0
src/Capacitor.Cli.Core/Pi/PiMcpExtensionInstaller.cs Pi's MCP bridge gains analytics — the only harness missing it; the tour's menu query needs query_analytics, and on Pi it would have degraded permanently
README.md, kcap/README.md, help-plugin.txt skill lists + the post-setup pointer
tests SourceNames mirror + a guard pinning it to the installer; CTA wording; CTA-phrase-in-frontmatter guard

Provenance of the skill content

The skill was authored and iterated against live trials outside this repo (kcap-quickstart-eval @ c6717f1). It landed here verbatim and was then changed deliberately, in review. It is no longer byte-identical to that source — here is every deviation and why:

Adaptations for shipping in the plugin

  • name: kcap-guided-tourname: guided-tour, matching the existing short-name convention (recap, errors, …). AgentsSkillsInstaller.RewriteNameFrontmatter re-prefixes it to kcap-guided-tour on copy for non-Claude vendors.
  • The Never bullet "curate apply …, kcap-memory, kcap-flows — empty or inert on day one" → scoped to "typically … on a fresh workspace". The original asserted something about every org.

Changed in review

  • The description's trigger list gained "Start kcap guided tour" — the phrase the setup CTA tells users to type. A test pins the two together.
  • Q-COST rewritten to pre-aggregate cost per session before joining (see below), then extended to carry the whole table; Q-ERR was first pruned (WHERE t.errors > 0) and later folded away entirely by the tool calls change below.
  • Session recall now precedes evals in the menu, the TODO list and the marker table. Recall pays off on day one; evals need a body of scored sessions first. The standalone "Learn how to reduce token cost and hours wasted" line under the table was dropped with it.
  • Each menu section opens with one plain descriptive sentence. Evals deliberately describes only the day-one capability (an LLM-judge score of one session), not the curation pipeline a fresh workspace can't show; PR review promises "why the code was written", not "discarded alternatives" a transcript may not hold.
  • The table's hours column became tool calls, and the whole table is now one query. v_an_sessions.duration_min is wall clock (ended_at - started_at) — sessions left open dominate it, and the schema itself labels it ELAPSED / not-human-effort. Time-based replacements were investigated and rejected: every duration surface in the views brackets human decisions (details in kurrent-io/kcap-server#1189). A count is immune, and it gives tool errors the denominator it never had. Both counts come from v_an_session_steps — the same view — so the error rate a reader computes is internally consistent; Q-ERR folded away entirely and beat 1 shrank to three parallel calls. Verified through the governed /api/analytics/query endpoint.
  • Welcome variants ask for the wait explicitly — each of the ten now says hang tight / give it a few seconds / hold on rather than implying it; hook sentences untouched. The table's cost column is headed LLM cost (USD).
  • All eight menu prompts reworked for a solo user, trigger keywords, and bounded turns. The originals assumed a team ("has anyone hit this before?" typed cold on a one-person record answers "nobody else") and one needed a stopword workaround to be answerable at all (deleted with it). Each prompt now pays off on the user's own record, carries the vocabulary its target skill advertises (so retyping it in a fresh session routes correctly), and cannot trigger a turn over ~2 minutes — the eval handler confirms before the 1-3 minute judge run, and the menu-context PR review is a bounded summary-plus-reasoning form. A new rule makes the skill assume the user works alone when composing its own prompt suggestions, unless their data has already shown other authors.
  • Live-test round (manual runs in a fresh session drove these): menu prompts must be REAL retypeable prompts, never consent tokens like go (with the skip-navigation exception); every step and turn 1 close with a docs link; step formatting rules (bold step header, tables for results, takeaway in bold); the tour entry point leads each section; LLM cost (USD) column header; explicit wait cues in all ten welcome variants (two also fixed to obey the skill's own no-analogy / no-savings-claim rules); the frontmatter description no longer hard-codes any invocation id (it advertised /kcap:guided-tour, which does not exist on non-plugin surfaces and misled invocation in a live run).
  • Turn-1 performance (live runs showed the budget blown): Q-COST and Q-PR merged into one Q-MENU call (pr_ref rides every row via LEFT JOIN ... ON TRUE; verified through the governed endpoint); Q-DONE disabled outright — its marker search returned ~100KB of snippets even at limit: 20 — with markers still emitted for when a server-side snippet cap exists; the import TODO ticks off Q-MENU's session counts instead; deferred-MCP hosts load tool schemas in one batched call.
  • New section: WHEN EVALS ARE NOT DEMONSTRABLE YET. Evals are a pipeline — score a session, accumulate facts across many, promote guidance, write it to CLAUDE.md — and only the first stage fits inside a tour. On a fresh workspace the rest is empty. The skill now checks reach before promising (its own search_sessions lookup at limit: 1, reading the author's session count off the response envelope, plus curate apply --dry-run, which reports without writing) and falls back to onboarding: run one real eval on the user's own session, read those scores, step through what the rest needs, then show a clearly-labelled illustration. That illustration is the one sanctioned exception to the skill's "their data, always" rule, which now names it rather than contradicting it.

The marker tokens (PromptedStartEvalsTour etc.) are unchanged — earlier tours match on them across sessions, so only their ordering moved.

Notes on scope

  • No .codex-plugin version bump. kcap/skills/ is a single shared tree — Claude reads it in place via the marketplace entry; every other vendor gets a copy from AgentsSkillsInstaller. .codex-plugin/plugin.json only points at ./.codex-mcp.json, which this PR doesn't touch, and it has never been bumped in lockstep since the rename commit.
  • No server changes. The tour's queries read v_an_* analytics views, part of the server's governed schema.
  • Public-repo check. Zero hits for usernames and zero 16+-hex-character runs in the skill file; zero occurrences of /kcap-guided-tour repo-wide.
  • All eight docs URLs in the skill's DOCS table return 200.

Review changes applied

  • The setup CTA is gated on the tour being actually runnable (5 findings across both reviewers, iterated to ground truth). Final form: an agent CLI is detected, AND skills/guided-tour/SKILL.md exists at a surface an agent would load it from — the registered Claude marketplace path read back from settings (kcap/legacy keys, matching IsInstalled), falling back to this build's plugin dir only when nothing is registered, or the shared/Kiro/Antigravity skills dirs. Every clause is a file-existence check on the artifact itself; install-result flags are deliberately not used because installers report false on already-current. Negative tests pin each failure mode found on the way: skip-flags, upgrade-from-older-skills, empty folder after failed copy, empty dir defaults, stale plugin dir, legacy-only registration.
  • CTA is a prompt, not a slash command. A slash command is vendor-specific — /kcap:guided-tour only works through the Claude Code plugin, while under ~/.agents/skills the skill is kcap-guided-tour. The prompt works everywhere. That made the skill's advertised triggers part of the contract, so a test now fails if the CTA and the skill's triggers drift apart.
  • Q-COST (Qodo). SUM(DISTINCT s.duration_min) dedupes by duration value across the whole repo bucket rather than by session. Verified against a live tenant: the shipped query is correct on current data — duration_min is a 16-decimal-place quotient and the only repeated value among cost-bearing sessions is NULL, which SUM ignores; both variants returned a 0.0 hour delta on every top repo. So it was a latent hazard resting on an unenforced property of a view in another repo, not a live defect. Fixed anyway, and the replacement is smaller: pre-aggregating v_an_cost (one row per session per model) to one row per session makes the join 1:1, so both DISTINCT crutches are deleted.
  • Q-ERR (Qodo). Flagged as an unbounded query in the menu's critical path. Measured at 78 rows. Both suggested bounds are worse: bounding by error count is measurably wrong — Q-ERR is a lookup consulted after Q-COST has chosen the rows, and one repo sits 3rd by cost but 7th by errors, so a top-5-by-errors limit would render 0 where the real count is 271; fusing it into Q-COST via a CTE serialises two calls beat 1 deliberately dispatches in parallel. Took the free prune instead: errors > 0, verified to drop 78 rows to 62 with identical totals and zero repos whose count changed, plus prose recording why there is no LIMIT.
  • Verbose comments (Qodo). 11 lines of commentary around a three-line print, against CLAUDE.md's self-explanatory-code rule. Trimmed to 4.
  • CTA-trigger test too weak (Qodo). It asserted Contains() over all of SKILL.md while claiming to pin the frontmatter. Vendors match on the frontmatter description only. Now slices the YAML block and asserts inside the description value; proven by mutation — moving the phrase into the body fails the test, where the old assertion passed.
  • Dismissed: a reported Linear id (AI-794) in the new spec file. It isn't there, and isn't on any line this PR adds — the string occurs once in the repo, in pre-existing README.md text two lines below the edited block.

Verification

Live-run

  • kcap plugin install --skills (scratch HOME, KCAP_PLUGIN_DIR → this worktree) writes ~/.agents/skills/kcap-guided-tour/SKILL.md with name: kcap-guided-tour, alongside the other six.
  • kcap setup --server-url <stub> --no-prompt exits 0 and closes with the call-to-action panel.
  • Both rewritten queries executed against a live tenant through the governed /api/analytics/query endpoint — accepted, correct shape, and equivalence to the previous versions confirmed by running old and new in a single query at one instant.

Tests. Unit suite 3954/3969 pass, 9 skipped, 6 failed — every failure in a rotating set of pre-existing timing / temp-file flakes. The failing subset differs run to run, none of it is code this PR touches, and the flakiest of them fails on unmodified origin/main too (sampling numbers in a comment below). AOT publish clean: zero IL2026/IL3050 warnings.

NOT exercised by any live run — prompt paths this repo's test suite cannot cover. They rest on the pre-merge trials, and the reordered menu and the new evals-fallback section have not been through a trial:

  • Install pathwhoami fails → tour degrades to setup help.
  • Import path — no sessions of the user's own → offer to import, then re-show the table.
  • Empty-table pathQ-COST returns nothing → table replaced by the import offer.
  • Evals fallback — the new not-yet-demonstrable branch, including the curate apply --dry-run readiness probe and the labelled illustration.
  • Marker round-trip — a completed tour emits ✓ Prompted<Id>Tour; a later tour in another repo finds it and crosses the TODO out.
  • Long-operation progress notes — the kcap eval step (1–3 min, backgrounded).
  • Degrade-never-stall timing — the ~15s query budget and the fallback line.
  • Invocation end-to-end. Neither /kcap:guided-tour nor the "Start kcap guided tour" prompt was driven end-to-end in a real agent session. Frontmatter parses and is discovered as a skill, and the ~/.agents/skills install path is verified live, but the trigger-to-tour hop is unproven here.

Server-side follow-up filed

Rendering turn 1 against real data showed the original column was not credible — is wall clock, so sessions left open dominate it. Resolved in this PR by replacing the column with (see above). The underlying data-semantics problem — all three duration surfaces in the governed views bracket human decisions — is filed as kurrent-io/kcap-server#1189 with the projection-level fix paths.

🤖 Generated with Claude Code

A user who finishes `kcap setup` is recording and has no idea what that
buys them. Every skill we ship today assumes the user already knows what
Capacitor does and which surface they want.

Adds `kcap/skills/guided-tour/SKILL.md` — the onboarding path: the team's
recorded sessions, spend and errors, then per-use-case tutorial tours
(evals, session recall, PR review, analytics), plus the missing-pieces
paths (offer to install kcap, offer to import history).

Skill content is verbatim from the trialled source; the only edits are the
short frontmatter name (matching `recap`/`errors`) and scoping the
"empty or inert on day one" claim to a fresh workspace.

Registered in AgentsSkillsInstaller.SourceNames so it reaches Codex,
Cursor, Kiro and Antigravity, not just Claude Code. Setup now closes with
a call-to-action panel whose wording is pinned by a test.

Also derives CodingAgentsStep's installed-skills line from SourceNames —
the hand-maintained copy had already drifted (printed `review-flows`
without its `kcap-` prefix).

Closes #368

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

linear-code Bot commented Jul 26, 2026

Copy link
Copy Markdown

AI-1530

/// with the skill's actual invocation name.
/// </summary>
internal const string GuidedTourCallToAction =
"New here? Run /kcap:guided-tour in your agent for a guided tour of what got recorded.";

@stktung stktung Jul 26, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Let's change the CTA to 'Prompt "Start kcap guided tour" in your agent for a guided tour of Capacitor'

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in e0ffee4 — the CTA is now exactly:

Prompt "Start kcap guided tour" in your agent for a guided tour of Capacitor

Verified live: kcap setup closes with that panel.

Agreed it's the better call, and it changed the contract in a way worth flagging. A slash command is vendor-specific — /kcap:guided-tour only resolves through the Claude Code plugin, while under ~/.agents/skills the skill is kcap-guided-tour. A prompt works everywhere.

But that also means the phrase we tell users to type has to be something the skill actually advertises, and it wasn't. So I added "Start kcap guided tour" to the skill's frontmatter trigger list, and a test (GuidedTourCallToAction_prompt_is_a_trigger_in_the_skill_description) that reads kcap/skills/guided-tour/SKILL.md and fails if the CTA and the skill's triggers ever drift apart.

That is an edit to a file the brief called final — I judged it in scope because it's the frontmatter (already being adapted for name:), not the tour body. Happy to pull it back out if you'd rather the description stay untouched, but then the only discovery path we ship rests on the agent inferring the trigger.

stktung and others added 2 commits July 27, 2026 03:54
PluginCommandCodexTests.SourceNames_contains_expected_skills asserts the
installer's list explicitly, so adding a skill has to be a conscious edit
there too. Keeping that deliberate — it's the intended gate.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Per review on #369: the setup call-to-action is now
`Prompt "Start kcap guided tour" in your agent for a guided tour of Capacitor`.

A natural-language prompt travels better than a slash command — the
invocation differs per vendor (/kcap:guided-tour via the Claude Code
plugin, kcap-guided-tour under ~/.agents/skills) while the prompt works
everywhere.

Adds the phrase to the skill's trigger list, and a test pinning the two
together: if we tell users to type a phrase the skill doesn't advertise,
the only discovery path we ship depends on the agent guessing.

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

stktung commented Jul 26, 2026

Copy link
Copy Markdown
Contributor Author

/review

@stktung

stktung commented Jul 26, 2026

Copy link
Copy Markdown
Contributor Author

Test + AOT results

AOT publish — clean. dotnet publish -c Release succeeds, zero IL2026/IL3050 warnings. (An earlier failure was vswhere.exe not on the shell's PATH at the native-link step — local environment, not the code.)

Unit suite — 3954 passed / 9 skipped / 6 failed of 3969.

No failure is in code this PR touches, and every test this PR adds or changes passes:

test
SetupCommandTests.GuidedTourCallToAction_is_the_exact_agreed_wording pass
SetupCommandTests.GuidedTourCallToAction_prompt_is_a_trigger_in_the_skill_description pass
AgentsSkillsInstallerTests.* (incl. the new SourceNames mirror guard) pass
PluginCommandCodexTests.SourceNames_contains_expected_skills pass

On the 6 failures

They are a rotating set — the failing subset differs between full runs, which is the signature of load-sensitivity rather than a deterministic break:

  • run A: ImportChainsAsync_dispatches_independent_chains_in_parallel, Retry_pending_obeys_cooldown_and_then_heals, Orchestrator_returns_ready_fragment_only_to_commit_winner, still_growing_line_completes_within_the_window_returns_true, Completion_guarantee_expires_at_thirty_day_sweep_boundary, Sweep_advances_past_poison_record
  • run B: same first three, plus drains_current_session_first_then_others_in_fifo and ShutdownFinalDrain_RealGrowingFile_HeldUntilComplete_ThenSentAndAdvanced, minus two of run A's

Failure modes are timing budgets (Expected to be less than 160 but received 180.8) and IOException: file … is being used by another process on %TEMP% files. Run in isolation, ImportChainsTests, HookSpoolTests and SessionStartMemoryFoundationTests are 36/36 green on this branch.

One caveat I could not fully close

LiveWatchHardeningAcceptanceTests.ShutdownFinalDrain_RealGrowingFile_HeldUntilComplete_ThenSentAndAdvanced flakes in isolation, so I baselined it against a detached worktree at origin/main (806acc2):

fail rate, class run in isolation
this branch 5 / 10
origin/main 1 / 15

So it is proven flaky on unmodified main — but the rate on this branch was higher, and I am not going to pretend I explained that away. Two things argue it is environmental: the branch rate climbed over the session (1/4 early → 4/6 late) while the machine accumulated 30 orphaned kcap watcher processes churning %TEMP%, and main only started failing once conditions had degraded to that point. And there is no execution path from this diff — a string added to SourceNames, a const, and two console lines — into a transcript-drain test.

I left the orphaned kcap processes alone rather than killing them, since they are this session's own hook/watcher processes and reaping them risks losing transcript data. Worth a re-run on a quiet machine or in CI before treating the rate difference as real.

@qodo-code-review

qodo-code-review Bot commented Jul 26, 2026

Copy link
Copy Markdown

Code Review by Qodo

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

Grey Divider


Action required

1. CTA checks wrong skill ✓ Resolved 🐞 Bug ≡ Correctness
Description
SetupCommand.ShouldOfferGuidedTour treats agent-skill installation as true when any kcap skill
folder (or marker) exists, not specifically when kcap-guided-tour is present, so setup can print the
guided-tour CTA even when guided-tour can’t be invoked for non-Claude agents. This contradicts the
spec’s stated intent (“only when the guided-tour skill is actually on disk”) and is plausible for
users upgrading from older installs that predate guided-tour.
Code

src/Capacitor.Cli/Commands/SetupCommand.cs[R557-563]

+    internal static bool ShouldOfferGuidedTour(
+            bool anyAgentDetected, string claudeSettingsPath, CodingAgentsStep.Paths paths) =>
+        anyAgentDetected
+     && (ClaudePluginInstaller.IsInstalled(claudeSettingsPath)
+      || AgentsSkillsInstaller.IsInstalled(paths.AgentsSkillsDir)
+      || AgentsSkillsInstaller.IsInstalled(paths.KiroSkillsDir)
+      || AgentsSkillsInstaller.IsInstalled(paths.AntigravitySkillsDir));
Evidence
ShouldOfferGuidedTour gates the CTA on AgentsSkillsInstaller.IsInstalled(...) for agent skill
directories, but IsInstalled is satisfied by the presence of any kcap skill folder (or marker),
which does not guarantee kcap-guided-tour exists; the spec says the CTA should only print when
guided-tour is actually on disk.

src/Capacitor.Cli/Commands/SetupCommand.cs[540-563]
src/Capacitor.Cli.Core/AgentsSkillsInstaller.cs[90-103]
docs/superpowers/specs/2026-07-27-guided-tour-skill-design.md[64-71]

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

### Issue description
`ShouldOfferGuidedTour` currently uses `AgentsSkillsInstaller.IsInstalled(...)`, which returns true if *any* kcap skill directory exists (or the marker file exists). This can cause `kcap setup` to show the guided-tour CTA even when `kcap-guided-tour` isn’t present (e.g., upgraded machines with only older skills like `kcap-recap`).

### Issue Context
- The design spec explicitly says the CTA prints only when the guided-tour skill is actually on disk for some agent.
- `AgentsSkillsInstaller.IsInstalled` is intentionally broad (marker OR any skill folder) for upgrade-refresh gating; it’s too broad for “guided-tour is available” gating.

### Fix Focus Areas
- src/Capacitor.Cli/Commands/SetupCommand.cs[540-563]

### Suggested fix
- Replace the `AgentsSkillsInstaller.IsInstalled(dir)` checks inside `ShouldOfferGuidedTour` with a guided-tour-specific check, e.g.:
 - `Directory.Exists(Path.Combine(dir, "kcap-guided-tour"))`
 - or introduce a helper like `AgentsSkillsInstaller.HasSkill(dir, "guided-tour")` and use that.
- Consider applying the same “specific presence” logic for Kiro/Antigravity skill dirs as well (not just the shared `~/.agents/skills`).

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



Remediation recommended

2. Invalid session_count lookup ✗ Dismissed 🐞 Bug ≡ Correctness
Description
The guided-tour eval readiness check instructs reading resolved_author.session_count from a
search_sessions response, but the sessions MCP tool is documented/implemented as a pass-through of
ranked hits JSON and does not define that envelope field. This makes the readiness gate unreliable
and can cause the tour to incorrectly conclude whether sessions exist for demonstrating evals.
Code

kcap/skills/guided-tour/SKILL.md[R418-421]

+  - **Sessions to score**: one `search_sessions` call here — `author: "<user>"`, `limit: 1`,
+    empty query — and read the response's `resolved_author.session_count` (`no_author_match`
+    means zero). Do NOT widen the limit; the count rides the envelope, not the results. One or
+    two sessions cannot produce a cross-session pattern.
Evidence
The skill explicitly depends on resolved_author.session_count for readiness, but repo
documentation and tests show search_sessions returns ranked hits and is forwarded as raw JSON text
(with no additional envelope added by the CLI), so the referenced field is not established by the
tool contract in this codebase.

kcap/skills/guided-tour/SKILL.md[416-421]
README.md[395-398]
test/Capacitor.Cli.Tests.Integration/McpSessionsServerTests.cs[225-252]
src/Capacitor.Cli/Commands/McpSessionsServer.cs[200-251]

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

### Issue description
`kcap/skills/guided-tour/SKILL.md` instructs the agent to read `resolved_author.session_count` from `search_sessions` to decide eval readiness. In this repo, `search_sessions` is documented as returning ranked hits, and the MCP server forwards the server body as text, so the skill should not depend on a `resolved_author.session_count` field.

### Issue Context
- `search_sessions` is described as returning ranked hits (session_id/snippet/etc), not an author-resolution envelope.
- The MCP server integration tests assert that the tool response is the raw JSON body returned by the server, carried inside `result.content[0].text`.

### Fix
Update the eval readiness check to use a field that is actually guaranteed by the documented response shape. For example:
- Call `search_sessions` with `author: "<user>"`, `query: ""`, `limit: 1`.
- Parse the JSON text and treat `hits.length > 0` as “has sessions”.
- Remove the claim that “the count rides the envelope” and the `resolved_author.session_count` / `no_author_match` logic.

### Fix Focus Areas
- kcap/skills/guided-tour/SKILL.md[418-421]

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


3. Bare PR ref used ✓ Resolved 🐞 Bug ≡ Correctness
Description
The guided-tour PR-review section uses prompts like review PR# {{PR}} and then instructs calling
kcap-review tools without ensuring a resolvable pr reference. Because kcap-review requires
pr: "owner/repo#123" or a PR URL (or else successful branch-based auto-detection), this can error
out or review the wrong PR when the user isn't on the relevant PR branch.
Code

kcap/skills/guided-tour/SKILL.md[R330-337]

+**`review PR# N`** — `kcap-review` MCP: `get_pr_summary`, then `get_transcript` /
+`search_context` for the reasoning. Show *why*, not just what changed. From the menu this is the
+BOUNDED form — summary plus the recorded reasoning behind the main changes, about a minute, NOT
+a line-by-line review of every file — and it ends with `Prompt ❯` offering the full deep review.
+
+**`Why was PR# {{PR}} implemented this way?`** — the reasoning half of the above on its own:
+`get_pr_summary` for what changed, then `get_transcript` / `search_context` for the decisions
+and constraints behind it. Attribute per the accuracy rules — who proposed, who decided.
Evidence
The guided-tour content presents PR review prompts using only a PR number and instructs
kcap-review tool usage, but the kcap-review MCP server contract requires an explicit pr
reference (owner/repo#N or URL) unless it can auto-detect from an open PR on the current branch;
otherwise it returns an error telling the caller to pass pr.

kcap/skills/guided-tour/SKILL.md[209-213]
kcap/skills/guided-tour/SKILL.md[330-337]
src/Capacitor.Cli/Commands/McpReviewServer.cs[268-277]
src/Capacitor.Cli/Commands/McpReviewServer.cs[345-366]

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 guided-tour skill’s PR review flow uses a bare `PR# {{PR}}` prompt and describes calling `kcap-review` tools without guaranteeing a usable `pr` reference. The `kcap-review` MCP server requires either an explicit `pr` argument in `owner/repo#123` form (or a PR URL), or it must be able to auto-detect an open PR from the current branch; otherwise it returns an error.

### Issue Context
This is within the guided-tour’s PR review tutorial content, so users can hit tool-call errors or get PR context that doesn’t match the prompt they typed.

### Fix Focus Areas
- kcap/skills/guided-tour/SKILL.md[209-213]
- kcap/skills/guided-tour/SKILL.md[330-337]

### Suggested fix
Update the PR-review prompts/instructions to explicitly require a repo-qualified PR reference or URL (e.g., prompt examples like `review owner/repo#{{PR}}` if you can construct it, or `review <paste PR URL>`), and instruct the agent to pass that as the `pr` argument on `get_pr_summary`/`search_context`/etc. If the skill can’t reliably derive `owner/repo`, have it ask the user to paste a PR URL before proceeding with the PR-review path.

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


4. Welcome overclaims and analogizes ✓ Resolved 🐞 Bug ≡ Correctness
Description
TEMPLATE PART A can be emitted verbatim on Turn 1, but variant 9 uses an explicit analogy ("Warming
up the memory banks") and variant 10 claims "cheaper sessions", contradicting the skill’s own
constraints ("No analogies" / no unsupported savings). Because the variant is chosen at random, this
rule violation will intermittently surface in real guided-tour runs and undermines the prompt’s own
non-negotiable guidance.
Code

kcap/skills/guided-tour/SKILL.md[R169-175]

+9  # 👋 Welcome to the Capacitor Guided Tour
+   Warming up the memory banks... your team's sessions are on their way. Hang tight — this
+   won't take long.
+
+10 # 🚀 Capacitor Guided Tour
+   Fewer repeated mistakes, cheaper sessions, answers from your team's history — that's the
+   tour in one line. Proof loads in a few seconds — hold on...
Evidence
The skill explicitly bans analogies and overclaiming/savings, but the newly edited welcome variants
include both an analogy and a cost-savings claim; because the template must be emitted verbatim and
selected randomly, the contradiction is operational (not theoretical).

kcap/skills/guided-tour/SKILL.md[22-28]
kcap/skills/guided-tour/SKILL.md[169-175]
kcap/skills/guided-tour/SKILL.md[334-336]

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 guided-tour skill forbids analogies and unsupported savings claims, but two of the fixed, verbatim welcome variants violate those rules (analogy: “memory banks”; benefit claim: “cheaper sessions”). Since the welcome variant is chosen at random and must be emitted verbatim, these phrases will be shown to users and contradict the skill’s own “non-negotiable” constraints.

### Issue Context
This is part of the Turn 1 fixed menu output; inconsistencies here are high-visibility and will recur.

### Fix Focus Areas
- kcap/skills/guided-tour/SKILL.md[137-176]

### Suggested fix
Edit variant 9 and variant 10 to remove figurative language and any implied cost-savings claim. Keep the language literal and evidence-compatible (e.g., “Fetching your team’s sessions now…”; “I’m pulling your sessions, spend, and tool errors…”).

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


View more (12)
5. Legacy marketplace path skipped ✓ Resolved 🐞 Bug ≡ Correctness
Description
ClaudePluginInstaller.RegisteredMarketplacePath only reads extraKnownMarketplaces.kcap.source.path
even though IsInstalled treats legacy marketplace keys (kurrent/kapacitor) as installed. For users
upgrading from those legacy registrations, SetupCommand.ClaudeCarriesGuidedTour can fall back to
pluginDir (a different directory than Claude actually loads), causing the guided-tour CTA to be
incorrectly shown or suppressed.
Code

src/Capacitor.Cli.Core/ClaudePluginInstaller.cs[R79-83]

+            var path = root["extraKnownMarketplaces"]?["kcap"]?["source"]?["path"];
+
+            return path is JsonValue v && v.TryGetValue<string>(out var p) && !string.IsNullOrWhiteSpace(p)
+                ? p
+                : null;
Evidence
IsInstalled documents and implements legacy-key recognition (kurrent/kapacitor), but
RegisteredMarketplacePath only reads the kcap key; ClaudeCarriesGuidedTour then uses that (possibly
null) value with a pluginDir fallback, so legacy registrations can cause checks against the wrong
directory. The added tests only exercise the modern kcap registration shape (via InstallPlugin), so
this legacy-path mismatch is not covered.

src/Capacitor.Cli.Core/ClaudePluginInstaller.cs[25-34]
src/Capacitor.Cli.Core/ClaudePluginInstaller.cs[74-83]
src/Capacitor.Cli/Commands/SetupCommand.cs[565-579]
test/Capacitor.Cli.Tests.Unit/SetupCommandTests.cs[349-383]

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

### Issue description
`ClaudePluginInstaller.RegisteredMarketplacePath()` only looks under `extraKnownMarketplaces.kcap.source.path`, but `ClaudePluginInstaller.IsInstalled()` explicitly recognizes legacy keys (`kurrent`, `kapacitor`) as indicating an installed plugin.

This mismatch means `SetupCommand.ClaudeCarriesGuidedTour()` may:
- **False-negative**: suppress the guided-tour CTA even though the legacy-registered marketplace dir contains `skills/guided-tour/SKILL.md`.
- **False-positive**: show the CTA based on `pluginDir` even though Claude is actually loading a different legacy-registered plugin directory that does *not* ship guided-tour.

### Issue Context
Legacy Claude settings keys are explicitly supported in detection/uninstall paths, so the “registered marketplace dir” lookup should be consistent with that legacy support.

### Fix Focus Areas
- src/Capacitor.Cli.Core/ClaudePluginInstaller.cs[68-87]
- src/Capacitor.Cli/Commands/SetupCommand.cs[572-579]
- test/Capacitor.Cli.Tests.Unit/SetupCommandTests.cs[349-383]

### Suggested fix
1. Update `RegisteredMarketplacePath()` to probe marketplace keys in a defined precedence order, e.g. `kcap`, then `kurrent`, then `kapacitor`, returning the first non-empty `source.path` it finds.
2. Consider rejecting obviously invalid paths (e.g., whitespace; optionally non-rooted paths) to avoid accidental relative-path probes.
3. Add a regression test that writes a settings.json with `extraKnownMarketplaces.kurrent.source.path` (and/or `kapacitor`) and asserts `ShouldOfferGuidedTour` behaves correctly when that registered directory contains/doesn’t contain `skills/guided-tour/SKILL.md` (including a case where `pluginDir` differs).

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


6. HasSkill docs overly verbose ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
The newly added XML doc for AgentsSkillsInstaller.HasSkill is longer than necessary and largely
restates behavior that the method name/signature already conveys. This increases documentation drift
risk and violates the guideline to keep comments concise.
Code

src/Capacitor.Cli.Core/AgentsSkillsInstaller.cs[R105-112]

+    /// <summary>
+    /// True when one specific owned skill is present under <paramref name="targetDir"/>. Narrower
+    /// than <see cref="IsInstalled"/>, which answers "has this installer ever run here" and is
+    /// also true for a machine carrying only skills from a version that predates
+    /// <paramref name="sourceName"/>.
+    /// </summary>
+    public static bool HasSkill(string targetDir, string sourceName) =>
+        Directory.Exists(Path.Combine(targetDir, "kcap-" + sourceName));
Evidence
PR Compliance ID 4 requires new/modified comments to be brief and not compensate for clarity that
could be in code. The added multi-line XML doc for HasSkill goes beyond what’s needed to explain a
simple directory existence check.

CLAUDE.md: Keep code comments concise and prefer self-explanatory code
src/Capacitor.Cli.Core/AgentsSkillsInstaller.cs[105-112]

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 XML doc comment added for `AgentsSkillsInstaller.HasSkill` is unnecessarily verbose and repeats details that can be inferred from the method name/implementation.

## Issue Context
Compliance requires concise comments that don’t restate obvious behavior.

## Fix Focus Areas
- src/Capacitor.Cli.Core/AgentsSkillsInstaller.cs[105-112]

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


7. Relative HasSkill check ✓ Resolved 🐞 Bug ≡ Correctness
Description
AgentsSkillsInstaller.HasSkill accepts an empty targetDir and will then check for a relative
"kcap-<name>" folder in the current working directory. Because CodingAgentsStep.Paths defaults some
skill-dir fields to empty strings, SetupCommand.ShouldOfferGuidedTour can incorrectly conclude
guided-tour is installed and show the CTA based on an unrelated repo-local ./kcap-guided-tour
directory.
Code

src/Capacitor.Cli.Core/AgentsSkillsInstaller.cs[R105-112]

+    /// <summary>
+    /// True when one specific owned skill is present under <paramref name="targetDir"/>. Narrower
+    /// than <see cref="IsInstalled"/>, which answers "has this installer ever run here" and is
+    /// also true for a machine carrying only skills from a version that predates
+    /// <paramref name="sourceName"/>.
+    /// </summary>
+    public static bool HasSkill(string targetDir, string sourceName) =>
+        Directory.Exists(Path.Combine(targetDir, "kcap-" + sourceName));
Evidence
The new HasSkill implementation does not validate targetDir, and SetupCommand uses it for multiple
skill directories. Since CodingAgentsStep.Paths provides empty-string defaults for some of those
directories, an unset path will cause HasSkill to probe the current working directory instead of an
intended skills directory, enabling false positives.

src/Capacitor.Cli.Core/AgentsSkillsInstaller.cs[105-112]
src/Capacitor.Cli/Commands/SetupCommand.cs[557-563]
src/Capacitor.Cli/Commands/CodingAgentsStep.cs[26-54]

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

### Issue description
`AgentsSkillsInstaller.HasSkill()` treats an empty `targetDir` as valid, which turns the existence check into a relative-path probe (e.g. `./kcap-guided-tour`). This can cause `SetupCommand.ShouldOfferGuidedTour()` to show the guided-tour CTA even when no agent actually has the skill installed.

### Issue Context
- `CodingAgentsStep.Paths` has several path fields with default `""` values.
- `ShouldOfferGuidedTour` calls `HasSkill` on those fields.

### Fix Focus Areas
- src/Capacitor.Cli.Core/AgentsSkillsInstaller.cs[105-112]
- src/Capacitor.Cli/Commands/SetupCommand.cs[557-563]

### Suggested fix
- Update `HasSkill` to return `false` when `targetDir` is null/empty/whitespace.
- (Optional extra hardening) Require `Path.IsPathRooted(targetDir)` if these are always expected to be absolute.
- Consider adding/adjusting a unit test that sets one of these dirs to `""` and creates a repo-local `kcap-guided-tour` directory to ensure the CTA remains suppressed.

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


8. Test asserts recap suffices ✓ Resolved 🐞 Bug ☼ Reliability
Description
The Kiro/Antigravity test creates only kcap-recap but asserts ShouldOfferGuidedTour is true, so
it doesn’t prove that guided-tour is actually present and will keep passing in the “upgraded from
old skills, guided-tour missing” scenario. This test effectively encodes the same overly-broad
predicate as correct behavior.
Code

test/Capacitor.Cli.Tests.Unit/SetupCommandTests.cs[R372-383]

+    public async Task ShouldOfferGuidedTour_true_from_the_kiro_and_antigravity_skill_dirs() {
+        using var kiro = new TempDir();
+        using var anti = new TempDir();
+
+        Directory.CreateDirectory(Path.Combine(kiro.Path, "kiro-skills", "kcap-recap"));
+        await Assert.That(SetupCommand.ShouldOfferGuidedTour(
+            true, Path.Combine(kiro.Path, "none.json"), GuidedTourPaths(kiro.Path))).IsTrue();
+
+        Directory.CreateDirectory(Path.Combine(anti.Path, "antigravity-skills", "kcap-recap"));
+        await Assert.That(SetupCommand.ShouldOfferGuidedTour(
+            true, Path.Combine(anti.Path, "none.json"), GuidedTourPaths(anti.Path))).IsTrue();
+    }
Evidence
The test’s setup uses kcap-recap (not kcap-guided-tour) and still asserts
ShouldOfferGuidedTour is true, so it cannot detect the bug where guided-tour is missing but older
skills exist.

test/Capacitor.Cli.Tests.Unit/SetupCommandTests.cs[371-383]

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

### Issue description
`ShouldOfferGuidedTour_true_from_the_kiro_and_antigravity_skill_dirs` currently creates `kcap-recap` and expects `ShouldOfferGuidedTour` to return true, which does not validate that `kcap-guided-tour` exists in those directories.

### Issue Context
If `ShouldOfferGuidedTour` is fixed to be guided-tour-specific, this test should be updated to match the intended contract. Even today, it provides false confidence by passing when only legacy skills are present.

### Fix Focus Areas
- test/Capacitor.Cli.Tests.Unit/SetupCommandTests.cs[371-383]

### Suggested fix
- Change the directory created in the test from `kcap-recap` to `kcap-guided-tour`.
- Add an explicit negative test case asserting `ShouldOfferGuidedTour` is false when only `kcap-recap` exists (and guided-tour does not).

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


9. Skipped test lacks coverage ✓ Resolved 🐞 Bug ⚙ Maintainability
Description
AgentSetupSkipped_is_true_only_on_the_two_early_returns claims to cover both early-return cases
but only asserts a manually constructed Result with AgentSetupRan: false, without exercising
CodingAgentsStep.RunAsync or the !options.InstallAgents early return. This test can pass even if
the real early-return behavior regresses, providing false confidence.
Code

test/Capacitor.Cli.Tests.Unit/SetupCommandTests.cs[R327-333]

+    [Test]
+    public async Task AgentSetupSkipped_is_true_only_on_the_two_early_returns() {
+        // No agent detected, and user declined — the two paths that install nothing at all.
+        var noAgents = new CodingAgentsStep.Result(false, false, false, false, false, AgentSetupRan: false);
+
+        await Assert.That(noAgents.AgentSetupSkipped).IsTrue();
+    }
Evidence
The test constructs CodingAgentsStep.Result(... AgentSetupRan: false) directly, so it only
verifies the derived property, not that RunAsync sets AgentSetupRan correctly on the two early
returns it contains (no agents and !options.InstallAgents).

test/Capacitor.Cli.Tests.Unit/SetupCommandTests.cs[327-333]
src/Capacitor.Cli/Commands/CodingAgentsStep.cs[146-159]

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 unit test for `AgentSetupSkipped` doesn’t validate the production behavior: it never invokes `CodingAgentsStep.RunAsync`, and it doesn’t cover both early-return conditions.

### Issue Context
`AgentSetupSkipped` now influences whether setup prints the guided-tour CTA, so regressions in the early-return wiring are user-visible.

### Fix Focus Areas
- test/Capacitor.Cli.Tests.Unit/SetupCommandTests.cs[327-333]
- src/Capacitor.Cli/Commands/CodingAgentsStep.cs[149-159]

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


10. CTA suppressed on success ✗ Dismissed 🐞 Bug ≡ Correctness
Description
SetupCommand now suppresses the guided-tour call-to-action when agent setup is skipped, so
successful setup runs where the user declines Step 4 (or no agents are detected) end without any
pointer to the guided tour. This contradicts the guided-tour design spec’s requirement that the CTA
prints unconditionally on successful setup and weakens discovery of the newly shipped skill.
Code

src/Capacitor.Cli/Commands/SetupCommand.cs[R540-548]

+        // Skipped agent setup means nothing is wired up to answer the prompt — pointing at the
+        // tour there would contradict the "no agent detected" warning printed moments earlier.
+        // An already-current install still prints: its Installed flags are false too.
+        if (!installResult.AgentSetupSkipped) {
+            AnsiConsole.Write(
+                new Panel($"[bold]{Markup.Escape(GuidedTourCallToAction)}[/]")
+                    .BorderColor(Color.Green)
+                    .Padding(1, 0));
+        }
Evidence
SetupCommand gates the CTA on !installResult.AgentSetupSkipped, and CodingAgentsStep sets
AgentSetupRan: false (making AgentSetupSkipped true) on both early-return paths (no agents
detected, or user declines unified install consent). The guided-tour design spec explicitly calls
for printing the CTA unconditionally on successful setup.

src/Capacitor.Cli/Commands/SetupCommand.cs[537-548]
src/Capacitor.Cli/Commands/CodingAgentsStep.cs[146-159]
src/Capacitor.Cli/Commands/SetupDecisions.cs[31-42]
docs/superpowers/specs/2026-07-27-guided-tour-skill-design.md[54-65]

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

### Issue description
`SetupCommand` currently prints the guided-tour CTA only when `installResult.AgentSetupSkipped` is false. This hides the CTA for successful setup runs where Step 4 is declined or early-returned, despite the onboarding requirement that setup should always point users to the guided tour.

### Issue Context
- `CodingAgentsStep.RunAsync` returns `AgentSetupRan: false` on both early returns (`no agents detected` and `!options.InstallAgents`).
- The design spec for the guided-tour skill states the CTA prints unconditionally on successful setup.

### Fix Focus Areas
- src/Capacitor.Cli/Commands/SetupCommand.cs[540-548]

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


11. Wrong beat reference ✓ Resolved 🐞 Bug ≡ Correctness
Description
The guided-tour skill says Q-DONE (author session count) is “already fetched in beat 1”, but the
same file’s Turn 1 protocol specifies Q-DONE is issued in beat 2 after whoami returns. This
contradiction can cause the agent to run Q-DONE too early or assume resolved_author.session_count
is available before it actually is, undermining the “menu first, TODO lookup later” orchestration.
Code

kcap/skills/guided-tour/SKILL.md[R354-357]

+**Establish which stage they can reach BEFORE opening the tour, and never promise past it.**
+Two read-only checks, no writes:
+  - **Sessions to score**: `resolved_author.session_count` from Q-DONE, already fetched in
+    beat 1. One or two sessions cannot produce a cross-session pattern.
Evidence
The Turn 1 orchestration explicitly schedules Q-DONE in Beat 2 (after whoami), but the later
evals-readiness section claims Q-DONE was fetched in Beat 1. These two statements cannot both be
true and directly affect tool-call ordering.

kcap/skills/guided-tour/SKILL.md[34-44]
kcap/skills/guided-tour/SKILL.md[354-357]

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

## Issue description
`kcap/skills/guided-tour/SKILL.md` contains contradictory guidance about when Q-DONE is executed:
- Turn 1 defines Q-DONE as a Beat 2 call (after `whoami`, alongside the menu body).
- The evals-readiness section later claims Q-DONE was already fetched in Beat 1.

This inconsistency can cause the agent to issue Q-DONE before it has `<user>` (or to assume session_count is already available), breaking the intended sequencing.

## Issue Context
Q-DONE depends on `<user>` returned by `kcap whoami`, so it cannot reliably be a Beat 1 parallel call.

## Fix Focus Areas
- kcap/skills/guided-tour/SKILL.md[354-357]

## Suggested fix
Change “already fetched in beat 1” to “already fetched in beat 2” (or reword to “already fetched earlier in turn 1 after whoami”), keeping the document’s beat definitions consistent.

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


12. Unbounded Q-ERR query ✓ Resolved 🐞 Bug ➹ Performance
Description
The guided-tour skill’s Q-ERR SQL groups errors by repo with no ORDER BY/LIMIT, so it can return
O(repo_count) rows even though the menu only needs error totals for the few repos shown from Q-COST.
This increases MCP/DB load and risks exceeding the skill’s intended ~12s menu budget (it will
degrade after ~15s, but the unbounded call is still avoidable).
Code

kcap/skills/guided-tour/SKILL.md[R79-86]

+**Q-ERR** (`scope: "global"`):
+
+```sql
+SELECT r.owner || '/' || r.repo_name AS repo, SUM(t.errors) AS errors
+FROM v_an_tool_usage t
+JOIN v_an_repositories r ON r.repo_hash = t.repo_hash
+GROUP BY r.owner || '/' || r.repo_name
+```
Evidence
The skill mandates Beat-1 parallel execution with a ~12s budget and provides a degrade-after-~15s
rule, but Q-ERR’s SQL has no limiting clause and groups by repo, so it can return one row per repo
across the org regardless of what the menu will display.

kcap/skills/guided-tour/SKILL.md[30-51]
kcap/skills/guided-tour/SKILL.md[79-86]

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

## Issue description
`guided-tour` runs Q-ERR in Beat 1 alongside Q-COST, but Q-ERR has no ordering/limit and can return one row per repository. The menu ultimately renders only a small table (derived from limited Q-COST), so this query can do far more work and return far more data than needed.

## Issue Context
The skill explicitly targets a fast Turn-1 menu (~12s) and suggests degrading after ~15s; however, we should still avoid intentionally unbounded queries in the hot path.

## Fix Focus Areas
- kcap/skills/guided-tour/SKILL.md[30-51]
- kcap/skills/guided-tour/SKILL.md[79-86]

## Suggested fix
Update Q-ERR to be bounded. Options:
1) Add `ORDER BY SUM(t.errors) DESC LIMIT <N>` (and optionally `WHERE t.errors > 0`).
2) Better: compute errors only for the same top repos used by Q-COST (e.g., via a CTE that selects the top 5 repos by cost and then LEFT JOINs tool usage), so Q-ERR returns at most 5 rows.

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


13. Linear ID AI-794 in doc ✗ Dismissed 📘 Rule violation ⚙ Maintainability
Description
The new design spec includes a Linear-style identifier (AI-794), which the checklist disallows in
comments/docs because it leaks internal tracking references. Replace it with a GitHub issue
reference (e.g., #...) or remove it if not necessary.
Code

docs/superpowers/specs/2026-07-27-guided-tour-skill-design.md[R67-72]

+6. **Version bump `kcap/.claude-plugin/plugin.json` 1.7.2 → 1.8.0.** Repo convention is a minor
+   bump per feature (1.6.0 → 1.7.0 added the flows MCP server; patch bumps were skill-behavior
+   fixes). `kcap/.codex-plugin/plugin.json` is left at 1.6.0: it has never been bumped in
+   lockstep since the rename commit, it declares only the Codex MCP server map, and nothing in
+   this change touches that map. Bumping it would imply a versioning contract that does not
+   exist.
Evidence
PR Compliance ID 5 forbids Linear issue identifiers in comments/docs. The added spec text explicitly
includes AI-794.

CLAUDE.md: Keep comments minimal; prefer self-explanatory code and avoid Linear issue numbers in comments
docs/superpowers/specs/2026-07-27-guided-tour-skill-design.md[67-72]

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 spec includes a Linear issue identifier (`AI-794`), which violates the guideline to avoid Linear IDs in comments.

## Issue Context
Compliance requires avoiding internal tracker references in repo text; prefer GitHub issue numbers if an issue reference is necessary.

## Fix Focus Areas
- docs/superpowers/specs/2026-07-27-guided-tour-skill-design.md[67-72]

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


14. CTA trigger test too weak ✓ Resolved 🐞 Bug ⚙ Maintainability
Description
GuidedTourCallToAction_prompt_is_a_trigger_in_the_skill_description claims to ensure the CTA
prompt is present in the skill’s description triggers, but it only checks that the phrase appears
anywhere in SKILL.md. This test would still pass if the phrase moved from YAML frontmatter to the
body, while discovery via description-based triggers could silently break.
Code

test/Capacitor.Cli.Tests.Unit/SetupCommandTests.cs[R263-272]

+    [Test]
+    public async Task GuidedTourCallToAction_prompt_is_a_trigger_in_the_skill_description() {
+        // The CTA sends users to a natural-language prompt, not a slash command. If that exact
+        // phrase isn't among the skill's advertised triggers, the only discovery path we ship
+        // depends on the agent guessing. Keep the two pinned together.
+        var skill = Path.Combine(RepoRoot(), "kcap", "skills", "guided-tour", "SKILL.md");
+
+        await Assert.That(File.Exists(skill)).IsTrue();
+        await Assert.That(await File.ReadAllTextAsync(skill)).Contains("Start kcap guided tour");
+    }
Evidence
The test reads the whole skill file and asserts a substring match, without parsing or even
constraining the match to the frontmatter/description block it says it is protecting.

test/Capacitor.Cli.Tests.Unit/SetupCommandTests.cs[254-282]
kcap/skills/guided-tour/SKILL.md[1-14]

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 test is intended to pin the setup CTA prompt to the skill’s *frontmatter description* (where vendors often derive triggers), but it currently does a file-wide `Contains`, which doesn’t actually validate that contract.

## Issue Context
The phrase currently appears in the YAML `description: >-` block, but the test should specifically assert it’s present in the YAML frontmatter (or even inside the description field) to prevent future regressions.

## Fix Focus Areas
- test/Capacitor.Cli.Tests.Unit/SetupCommandTests.cs[263-272]
- kcap/skills/guided-tour/SKILL.md[1-14]

## Suggested fix
In the test, extract the YAML frontmatter block (between the first two `---` lines) and assert the phrase appears within that block (optionally: within the `description:` field). Avoid adding heavy dependencies if possible; a simple frontmatter slice is sufficient for this pinning test.

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


15. Wrong hours SQL sum ✓ Resolved 🐞 Bug ≡ Correctness
Description
The guided-tour skill’s Q-COST query calculates hours using SUM(DISTINCT s.duration_min), which
deduplicates by the duration value rather than by session and will undercount whenever multiple
sessions have the same duration. This produces incorrect hours in the onboarding table shown to
users.
Code

kcap/skills/guided-tour/SKILL.md[R66-69]

+SELECT r.owner || '/' || r.repo_name AS repo,
+       COUNT(DISTINCT s.session_id) AS sessions,
+       ROUND(SUM(DISTINCT s.duration_min)/60.0, 1) AS hours,
+       ROUND(SUM(c.cost_usd)::numeric, 2) AS cost_usd
Evidence
The query explicitly uses SUM(DISTINCT s.duration_min), which sums unique duration values instead
of summing durations once per session, so multiple sessions sharing the same duration are collapsed
into one contribution.

kcap/skills/guided-tour/SKILL.md[63-76]

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

## Issue description
`Q-COST` in `kcap/skills/guided-tour/SKILL.md` computes hours as `SUM(DISTINCT s.duration_min)`, which is mathematically incorrect because `DISTINCT` applies to the numeric duration values (so two different sessions with the same `duration_min` are counted once).

## Issue Context
This query is intended to avoid join fan-out from `v_an_cost` while still summing session duration once per session. The correct approach is to deduplicate by `session_id` (or pre-aggregate to one row per `repo_hash, session_id`) before summing durations.

## Fix Focus Areas
- kcap/skills/guided-tour/SKILL.md[63-77]

### Example direction (one acceptable approach)
Rewrite `Q-COST` to pre-aggregate cost rows by `(repo_hash, session_id)` (or select distinct session ids per repo) and then sum durations without `DISTINCT`, e.g.:

- Build a per-session-per-repo set: `SELECT repo_hash, session_id, SUM(cost_usd) AS cost_usd FROM v_an_cost ... GROUP BY repo_hash, session_id`
- Join to `v_an_sessions` once per session and compute `SUM(s.duration_min)`
- Aggregate to repo for the final table

This avoids both duration undercounting and cost inflation from fan-out.

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


16. GuidedTourCallToAction comments too verbose ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
Newly added inline and XML doc comments around the guided-tour call-to-action are overly verbose and
restate behavior that could be conveyed via naming/structure. Long comments are more likely to drift
and reduce readability over time.
Code

src/Capacitor.Cli/Commands/SetupCommand.cs[R540-559]

+        // Setup leaves the user recording but with no idea what that buys them. The guided-tour
+        // skill is the answer, and nothing else points at it — so this is the last thing printed,
+        // in a panel, on every successful run. It prints even when no hooks were installed: the
+        // user may already have sessions from a prior install, and the tour degrades to offering
+        // install/import when they don't.
+        AnsiConsole.Write(
+            new Panel($"[bold]{Markup.Escape(GuidedTourCallToAction)}[/]")
+                .BorderColor(Color.Green)
+                .Padding(1, 0));
+
        return 0;
    }

+    /// <summary>
+    /// The end-of-setup nudge toward the guided-tour skill. A natural-language prompt rather
+    /// than a slash command, because the invocation differs per vendor (<c>/kcap:guided-tour</c>
+    /// via the Claude Code plugin, <c>kcap-guided-tour</c> under ~/.agents/skills) while the
+    /// prompt works everywhere. Held as a constant so the wording is pinned by a test and stays
+    /// in sync with the trigger phrases in the skill's description.
+    /// </summary>
Evidence
PR Compliance ID 3 requires avoiding overly verbose comments. The added comments at
SetupCommand.cs[540-544] and SetupCommand.cs[553-558] are multi-line explanations that restate
the rationale/behavior of printing the guided-tour CTA, rather than keeping commentary minimal.

CLAUDE.md: Avoid verbose comments; prefer self-explanatory code
src/Capacitor.Cli/Commands/SetupCommand.cs[540-559]

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 guided-tour CTA block adds verbose inline and XML doc comments that restate intent/behavior; this increases drift risk and hurts readability.

## Issue Context
Compliance requires avoiding overly verbose comments in favor of self-explanatory code.

## Fix Focus Areas
- src/Capacitor.Cli/Commands/SetupCommand.cs[540-559]

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



Informational

17. Stale Pi server-count comment ✓ Resolved 🐞 Bug ⚙ Maintainability
Description
The Pi MCP bridge now spawns five servers (analytics added), but the nearby comment still refers to
“four hung servers”, which is now inaccurate and can mislead future maintenance/debugging. This
inconsistency was introduced by extending the server list without updating the adjacent
documentation.
Code

src/Capacitor.Cli.Core/Pi/PiMcpExtensionInstaller.cs[29]

+        const KCAP_MCP_SERVERS = ["review", "sessions", "flows", "memory", "analytics"];
Evidence
The server list now contains five entries including analytics, while a later comment still
describes the concurrency benefit using the old count (“four”).

src/Capacitor.Cli.Core/Pi/PiMcpExtensionInstaller.cs[27-33]
src/Capacitor.Cli.Core/Pi/PiMcpExtensionInstaller.cs[305-307]

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

### Issue description
`KCAP_MCP_SERVERS` was extended to include `analytics`, making the bridge spawn five servers, but a later comment still describes the behavior in terms of “four hung servers”. This is now stale.

### Issue Context
The server list is a constant and easy to change over time; comments that hard-code the count tend to drift.

### Fix
Update the comment to either:
- say “five hung servers”, or
- avoid encoding a number (preferred), e.g. “multiple hung servers add ~10s wall-clock, not N×”.

### Fix Focus Areas
- src/Capacitor.Cli.Core/Pi/PiMcpExtensionInstaller.cs[29-33]
- src/Capacitor.Cli.Core/Pi/PiMcpExtensionInstaller.cs[305-307]

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


Grey Divider

Qodo Logo

Comment thread src/Capacitor.Cli/Commands/SetupCommand.cs Outdated
Comment thread kcap/skills/guided-tour/SKILL.md Outdated
@stktung

stktung commented Jul 26, 2026

Copy link
Copy Markdown
Contributor Author

/review

Qodo rule violation: CLAUDE.md asks for self-explanatory code over verbose
comments, and 11 lines of commentary around a three-line print is the
drift-prone narration that rule exists to prevent — it had already gone
stale once when the CTA wording changed.

Keeps the two non-obvious facts (prints unconditionally; wording is
test-pinned) and drops the rest. The prompt-vs-slash-command rationale is
enforced by GuidedTourCallToAction_prompt_is_a_trigger_in_the_skill_description,
which is a stronger guarantee than a paragraph asking readers to keep two
things in sync.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Comment thread docs/superpowers/specs/2026-07-27-guided-tour-skill-design.md
Comment thread kcap/skills/guided-tour/SKILL.md Outdated
Comment thread test/Capacitor.Cli.Tests.Unit/SetupCommandTests.cs
@qodo-code-review

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit e0ffee4

@stktung

stktung commented Jul 26, 2026

Copy link
Copy Markdown
Contributor Author

/review

@qodo-code-review

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit bb5614f

stktung and others added 4 commits July 27, 2026 05:14
Qodo: the test claimed the setup CTA's prompt is among the skill's
advertised triggers, but asserted Contains() over all of SKILL.md. Vendors
match on the frontmatter `description:` only — the body is read after the
skill fires — so the phrase could move below the fences, stop triggering
anything, and the guard would stay green.

Now slices the YAML frontmatter and asserts inside the description value.
Verified by mutation: moving the phrase from the description into the body
fails the test, where the old assertion passed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Qodo: `SUM(DISTINCT s.duration_min)` dedupes by duration VALUE across the
whole repo bucket, not by session, so two sessions sharing a byte-identical
duration would collapse into one.

Verified against a live tenant before and after: the shipped query is
correct on current data — `v_an_sessions.duration_min` is
`EXTRACT(EPOCH FROM (ended_at - started_at)) / 60.0`, a 16-decimal-place
quotient, and the only repeated value among cost-bearing sessions is NULL,
which SUM ignores. Running both variants in one query returned a 0.0 hour
delta on every top repo.

So this is a latent hazard, not a live defect: correctness rests on an
unenforced property of a view in another repo. Round durations to whole
minutes server-side and this silently starts eating sessions.

The replacement removes the dependency rather than documenting it.
`v_an_cost` is one row per (session, model), so pre-aggregating it to one
row per session makes the join 1:1 — and both DISTINCT crutches become
unnecessary and are deleted. Fewer moving parts than what it replaces.

Both versions confirmed to return identical hours and identical total cost.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Qodo flagged Q-ERR as an unbounded query in the menu's 12s critical path.
Measured: it returns 78 rows of (text, bigint) — not a payload that
threatens the budget.

Its two suggested bounds are both worse than the status quo. Bounding by
error count is measurably wrong: Q-ERR is a lookup consulted after Q-COST
has chosen the rows, and the two rank differently — one repo sits 3rd by
cost but 7th by errors, so `ORDER BY errors DESC LIMIT 5` would drop it
and the missing-repo rule would render 0 where the real count is 271.
Fusing Q-ERR into Q-COST via a CTE is correct but serialises two calls
beat 1 deliberately dispatches in parallel, trading a guaranteed
round-trip against a 78-row concern.

So: prune with `errors > 0`, which is free. Verified by running both
variants in one query at one instant — 78 rows becomes 62, identical
totals, and zero repos whose count changed. The 16 dropped rows are
all-zero repos that the missing-repo rule already renders as 0, so the
output is unchanged.

The prose above the query is the part that lasts: nothing recorded WHY
Q-ERR was unbounded, which is what let it read as an oversight.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ng demonstrable

Session recall now precedes evals in the menu, the TODO list and the marker
table. Recall works on day one with whatever the record already holds;
evals need a body of scored sessions before they show anything. Leading
with the use case that pays off immediately.

Drops the standalone "Learn how to reduce token cost and hours wasted"
line under the table — it promoted the evals tour from the position the
eye lands on first, which is now the wrong pitch to lead with.

Adds WHEN EVALS ARE NOT DEMONSTRABLE YET. Evals are a pipeline —
score a session, accumulate facts across many, promote guidance, write it
to CLAUDE.md — and only the first arrow fits inside a tour. On a fresh
workspace the later stages are empty, and staging a curation demo on a
record that cannot support one reads as a broken product.

The skill now checks reach before promising (session_count from Q-DONE,
plus `curate apply --dry-run`, which reports without writing) and falls
back to onboarding: still run one real eval on their own session, read
those scores, step through what the rest needs, then show a clearly
labelled illustration of the end state. That illustration is the single
sanctioned exception to "their data, always", so rule 3 now names it
rather than contradicting it, and the Never list carves out --dry-run
from the ban on `curate apply`.

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

stktung commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

/review

Comment thread kcap/skills/guided-tour/SKILL.md Outdated
@qodo-code-review

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 98b9b9c

stktung and others added 2 commits July 27, 2026 14:23
… reference

Each menu section now opens with one plain sentence saying what it does,
replacing copy that varied in length and register between sections.

Evals deliberately describes only the part that works on day one — an
LLM-judge score of one session. The previous copy sold cross-session
pattern-finding and curated repo guidance, which a fresh workspace cannot
show; promising it on the first screen is what WHEN EVALS ARE NOT
DEMONSTRABLE YET exists to avoid. That capability is now unadvertised in
the menu and lives in the tour body instead.

PR review says the sessions carry why the code was written that way,
rather than claiming "discarded alternatives" — a transcript may not
contain any, and the skill's honesty rules forbid promising what the data
might not hold.

Also fixes a contradiction Qodo caught in the new evals section: it said
session_count is fetched in beat 1, but Q-DONE needs <user> from whoami
and runs in beat 2. An agent following the wrong one could read the count
before it exists. Now names beat 2 and states the dependency inline.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Codex review: setup printed the guided-tour CTA unconditionally, so a
machine with no supported agent CLI got "No supported agent CLI detected"
and "Prompt \"Start kcap guided tour\" in your agent" in the same output.
Nothing was installed to answer that prompt.

Codex suggested gating on a successful skill/plugin/MCP install. That
would break the common case: the installers return false when work was
skipped as already-current, so every re-run with skills in place would
lose the CTA — exactly the users who can act on it.

Gated on the two early returns instead, which are the only paths that
install nothing at all. CodingAgentsStep owns that fact rather than
SetupCommand re-deriving the condition, so the two can't drift.

Verified live both ways: with an agent detected the panel prints; with
every detection route defeated (empty PATH plus each vendor's relocation
env var) the warning appears and the CTA does not.

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

stktung commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

/review

Comment thread src/Capacitor.Cli/Commands/SetupCommand.cs Outdated
Comment thread test/Capacitor.Cli.Tests.Unit/SetupCommandTests.cs
@qodo-code-review

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 58ab24d

Round-2 review found the previous gate wrong in both directions, so this
replaces it rather than patching it.

Codex: a Claude-only machine run with --skip-claude-hooks installs nothing,
yet AgentSetupRan stayed true and the CTA printed. Codex also caught that
adding a defaulted field to Result broke two existing equality assertions
in CodingAgentsStepTests — I had run only SetupCommandTests and reported
green, which is how that reached the branch.

Qodo: the design spec still said the CTA prints unconditionally. That was
true when written and stopped being true when the gate landed; the spec is
now updated with the revision and why.

Dropping AgentSetupRan/AgentSetupSkipped removes the broken assertions at
the cause. The replacement asks two direct questions instead of threading
install flags: is there an agent to type the prompt into, and is the skill
on disk for one of them. Skill presence is read from the filesystem
because the installers report false when work was skipped as
already-current — a wired-up machine re-running setup, which must still
get the CTA.

The agent-detected half was missing from every earlier attempt: a machine
carrying the skill but running no agent CLI has nothing to prompt. Neither
reviewer raised it; it surfaced writing the scenarios out.

Five tests cover the helper directly, replacing one that asserted against
a hand-built record and would have passed through a real regression.
Live-verified: no agent detected suppresses, agent plus skills present
prints. Agent present with nothing on disk is unit-tested only —
AgentsPaths.UserSkillsDir resolves from the real Windows profile
regardless of a HOME override, so a scratch harness cannot isolate it.

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

stktung commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

/review

Comment thread src/Capacitor.Cli/Commands/SetupCommand.cs Outdated
Comment thread test/Capacitor.Cli.Tests.Unit/SetupCommandTests.cs
@qodo-code-review

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 7974a63

…st labelled

Each of the ten welcome variants now asks the user to wait in so many
words — hang tight, give it a few seconds, hold on — instead of implying
it. The hook sentence of each variant is untouched; only the closing beat
changed, phrasing varied so the ten stay distinct. Time promises stay at
seconds/a moment, consistent with the ~12s menu budget.

The table's cost column is headed "LLM cost (USD)" — the bare number
needed its currency and its meaning on a first screen. The SQL alias
stays cost_usd: the rendered header comes from the template line, and the
"exactly as returned" rule governs values, not titles.

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

stktung commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

/review

Comment thread kcap/skills/guided-tour/SKILL.md
@qodo-code-review

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit fc652e6

…wo minutes

Every sample prompt reworked against three constraints from review of the
rendered menu:

Solo user. The old prompts assumed a team — "has anyone hit this before?"
typed cold answers "nobody else" on a one-person record, and "what did we
spend" presumes a we. All eight prompts now pay off on the user's own
record alone, and a new rule in Executing the menu makes the skill assume
the user works alone when composing its own Prompt suggestions, unless
their data has already shown other authors.

Trigger keywords. Menu prompts get retyped in fresh sessions (the marker
scheme depends on it), so each now carries the vocabulary the target
skill advertises: "my last session" / "left off" for recap, "show ...
tool errors" for errors, "review PR" and "why was ... implemented this
way" for kcap-review, "spend"/"cost" for analytics. The old "Recall the
last 3 times I asked why" needed a stopword workaround section to be
answerable at all — a demo requiring a workaround is the wrong demo; the
section is deleted with it.

Bounded turns. No menu prompt may trigger a turn over ~2 minutes: the
eval handler now asks for a go before the 1-3 minute judge run and
backgrounds it where the harness allows; the menu-context PR review is
the bounded summary-plus-reasoning form, ending with an offered prompt
for the full deep review.

Session recall also gains an action prompt — "Pick up where my last
session left off" resumes work rather than reporting on it, which is the
strongest first-screen proof that the record is working memory rather
than an archive.

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

stktung commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

/review

Comment thread kcap/skills/guided-tour/SKILL.md Outdated
@qodo-code-review

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit f463121

Qodo, two findings on the prompt rework.

Variant 9's hook was an analogy ("warming up the memory banks") under a
voice section that says no analogies, and variant 10 claimed "cheaper
sessions" — the savings claim the honesty rules explicitly say nothing
backs yet. Both emitted verbatim on a random draw, so the contradiction
shipped intermittently. Reworded to what the record does support.

Q-PR returned a bare number, but the kcap-review tools need
owner/repo#N (or a URL, or branch auto-detection) — so "review PR# 283"
retyped in a later session on an unrelated branch could fail to resolve
or resolve against the wrong repo, undercutting exactly the cross-session
retyping the prompts were reworked for. Q-PR now joins
v_an_repositories and returns the full ref (verified through the
governed endpoint), the prompts read `review {{PR}}`, and the handler
passes the ref explicitly rather than relying on auto-detection.

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

stktung commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

/review

"review <ref>" said what to do; "Review <ref> and its key decisions"
says what makes this review different — the recorded decisions behind
the diff. Same handler, same bounded form; "and its key decisions" also
steers the bounded menu review toward the reasoning summary rather than
a line-by-line pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
stktung and others added 7 commits July 27, 2026 18:42
Each section now opens with "Prompt ❯ `Start the <use case> tour` to
begin" directly under the header, before the description and sample
prompts. The tour is the guided path and belongs first; the samples are
the à-la-carte alternatives. The backticked phrase is unchanged, so the
completion markers and TODO matching are unaffected.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Observed in a live tour run: a step described the query it was about to
run and then offered `go` as the advance. Typing `go` teaches nothing —
the real phrasing stayed hidden in the step's prose, which defeats rule
2 (typing it IS the tutorial).

Composed prompt suggestions must now be the self-contained phrasing the
user would type in a fresh session — the advance for "I'll query your
last 7 days of spend" is the spend question itself, and variations are
full prompts too, not deltas like "make it 30 days instead". Pure tour
navigation (skip to ..., back to the menu) stays conversational by
design. Rule 5 cross-references the composition rules so the two can't
drift.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…for scanning

The table caption says whose sessions these are: "Your team's coding
agent sessions at a glance". A first-time reader doesn't yet know that
"session" means an agent conversation.

Tour steps now carry explicit formatting rules — bold step-number
header, results as markdown tables rather than sentences of numbers,
typed/run things in fenced code, the takeaway in bold, and a hard cap of
two or three short paragraphs before the Prompt lines. Observed in live
runs that steps drift toward prose walls without this.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…deferred tools

Live turn-1 runs surfaced three latency sinks.

Q-DONE is disabled outright. Even at limit 20 its marker search returned
~100KB of snippets, sinking the turn budget for a TODO checklist. The
markers are still emitted at tour completion so history accrues, but
nothing looks them up until the server offers a snippet-size cap or
marker-only search. Everything that leaned on Q-DONE is rewired: the
TODO list renders only what turn 1 can know (whoami for the install
line, this-conversation completions for tour lines), the no-sessions
fallback now triggers from the tours' own author lookup, and the evals
readiness check does its own search_sessions at limit 1, reading
resolved_author.session_count off the envelope rather than the results.

Q-PR gains scope global: the repo-scoped default probes the cwd for a
checkout and costs a retry when there is none, and since {{PR}} is a
full owner/repo#N ref the demo works from any directory.

Beat 1 now says to load deferred MCP tool schemas in ONE lookup in the
same message as the welcome — per-tool lookups are full round-trips
that serialise a beat designed to run parallel.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Q-COST and Q-PR merge into Q-MENU: the pr_ref rides along as a constant
column on the table rows (LEFT JOIN latest_pr ON TRUE, so an empty PR
view cannot empty the table). Both were scope-global already, and every
query_analytics call pays full transport — live turn-1 runs showed the
two calls serialising in practice, so the fix is not "run them in
parallel" but "stop there being two". Beat 1 is now whoami plus exactly
one MCP query. Verified through the governed endpoint.

The menu header gains the lightning bolt, and every tour step — plus
turn 1 itself — now closes with "Learn more:
https://capacitor.kurrent.io/docs" after the Prompt lines.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Live test: "start the kcap guided tour" matched the skill's description
(trigger matching worked), but the model then invoked kcap:guided-tour —
the plugin-namespaced id hard-coded inside the description text — instead
of the id the listing actually carried, and got "Unknown skill".

The installer rewrites name: per surface (guided-tour in the plugin,
kcap-guided-tour under ~/.agents, Kiro, Antigravity, personal copies) but
the description text never changes, so on every non-plugin surface it
advertised an id that does not exist there. The description now says
"invoke this skill directly by its listed name" and refers to "the recap
skill" rather than kcap:recap — no hard-coded ids to mislead invocation
on any surface.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
With Q-DONE disabled the import line rendered permanently unticked, which
reads as "you still need to import" to a user whose table two lines up is
full of sessions. Q-MENU already answers the question well enough: at
least one raw row with sessions >= 1 means the record has data, so the
TODO crosses out. Judged on the raw rows before the render filter, so a
solo user whose repos are all personal (filtered from display) still gets
the tick — the import offer only replaces the table when Q-MENU returned
nothing at all.

Team-wide is a looser proxy than the user's own count (which needs
Q-DONE), accepted until the marker lookup returns.

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

Copy link
Copy Markdown
Collaborator

@stktung

  1. Is this skill installed by default with our other skills as part of kcap-cli install as well?
  2. Want to make sure that all the coding agent harnesses can use this skill as well

Auditing whether the guided tour works on every harness found one hole:
Pi's kcap-mcp.ts bridge hardcoded review/sessions/flows/memory — no
analytics. The tour's menu query calls query_analytics, so on Pi the
skill installed fine (it rides the shared ~/.agents/skills tree) but
every tour would have opened with the degrade fallback, permanently and
silently.

Every other harness already carries kcap-analytics: the Claude plugin's
.mcp.json, Codex's .codex-mcp.json and TOML registration, and the
ForCursor set that Cursor/Copilot/Gemini/Kiro/OpenCode/Antigravity all
register. Pi was the one surface assembled from its own hardcoded list.

Existing Pi users pick the fixed bridge up automatically: the extension
carries a version marker the npm postinstall refresh rewrites on
upgrade.

Tests: CodingAgentsStepTests 131/131, SetupCommandTests 39/39; AOT
publish clean, zero IL2026/IL3050.

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

stktung commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

/review

Comment thread kcap/skills/guided-tour/SKILL.md
Comment thread src/Capacitor.Cli.Core/Pi/PiMcpExtensionInstaller.cs
@qodo-code-review

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 0c3279d

Qodo: adding analytics to KCAP_MCP_SERVERS made the "four hung servers"
comment stale. Reworded without a count, as suggested — comments that
hard-code the size of an adjacent list drift every time it grows.

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

stktung commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

@stktung

  1. Is this skill installed by default with our other skills as part of kcap-cli install as well?
  2. Want to make sure that all the coding agent harnesses can use this skill as well

Yes @realtonyyoung, it's added in the same way that is added same way the other skills are any Claude says it's good

image

@stktung

stktung commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

/review

@qodo-code-review

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 9833114

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.

Ship a Capacitor guided-tour skill and point new users at it from setup

2 participants