Skip to content

Commit e91a8bd

Browse files
authored
feat: parallel multi-agent verification, standards migration, blog & dashboard (#49)
* feat: parallel multi-agent verification, standards migration, blog section, and dashboard improvements Spec Workflow - Parallel Multi-Agent Verification: - Split monolithic spec-verifier into spec-reviewer-compliance (plan alignment, DoD, risk mitigations) and spec-reviewer-quality (code quality, security, testing, performance) - Add adversarial plan-challenger agent alongside plan-verifier for plan review phase - Both verification points now launch paired agents in parallel via Task() calls - Agents persist findings to session files for reliable retrieval across agent lifecycles - spec-verify early-launch pattern: review agents start at Step 3.0 and work in background while tests, lint, and feature parity checks run in Steps 3.1-3.4 - Update spec-plan.md, spec-verify.md, and workflow-enforcement.md for new agent topology - Update settings.json and tool_redirect.py whitelists for new agent types Standards Migration (Skills → Rules): - Convert 13 standards-* skills to concise conditional rules with frontmatter/glob patterns - Delete all pilot/skills/standards-* directories (3,967 lines removed) - Add 8 new standards rules files (957 lines) — accessibility, api, components, css, migration, models, queries, responsive - Rename standards-design from skill to rule; merge golang/python/typescript standards into existing language rule files - Add installer cleanup for legacy standards-* skill directories on upgrade Hooks System: - Add SessionEnd hook that only stops the worker when no other sessions are active - Replace raw bun worker-stop with Python session-aware shutdown - Add Bash matcher to PreToolUse hook for tool_redirect coverage - Add cross-session task isolation documentation to workflow-enforcement Console Dashboard: - Add VaultStatus card with sx Team Vault integration (installed assets, catalog, status) - Add VaultRoutes API endpoints for vault status and management - Refactor dashboard cards with Workspace badges and flexible height layout - Simplify VexorStatus and VaultStatus to display-only mode (remove interactive buttons) Marketing Website: - Add blog section with 19 SEO-optimized articles on Claude Code topics - Blog infrastructure: react-markdown rendering, typography plugin, search/filter/sort - 3D voxel logo component, scroll-to-hash navigation, cross-page routing - Sitemap with blog URLs, structured data for BlogPosting schema - Updated NavBar and Footer with blog links and cross-page section navigation Installer & Launcher: - Add discount code display for expired trials and failed license validations - Add sx update command alongside install - Test coverage for session_end hook, context cache cleanup, and banner display * fix: update VexorStatus widget tests for display-only mode The VexorStatus component was simplified to remove the Re-index button and interactive functionality. Update tests to match the new display-only behavior. * fix: address PR #49 review findings, eliminate blog metadata duplication, and update skills-to-standards references PR review fixes: - Add VaultRoutes API test coverage (13 tests: status caching, install concurrency, error handling) - Fix process kill reliability with SIGTERM-then-SIGKILL fallback - Add session ID validation with "default" fallback in spec-verify - Add 3-step fallback for missing findings files in spec-verify - Add loading skeleton UI to VaultStatus dashboard component Blog infrastructure: - Eliminate metadata duplication by adding YAML frontmatter to all 19 .md files - Rewrite index.ts to auto-discover articles via import.meta.glob - Delete all 19 per-article .ts export files (single .md file per article now) - Generate sitemap at build time via Vite plugin instead of static file - Show all category tags in filter bar instead of first 4 - Widen search bar for better usability - Fix rotating header animation with transition-based approach Documentation: - Update README and website to reflect skills-to-standards migration - Add Skills row to README for custom user skills created via /learn - Fix AgentRoster standards count (14 → 13) and listed domains - Add 400-line guidance for rule files to coding standards
1 parent e0bdfdc commit e91a8bd

File tree

124 files changed

+8648
-4579
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

124 files changed

+8648
-4579
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ playwright/
239239
docs/plans
240240
docs/license
241241
docs/video
242+
docs/slides
242243
.install-version
243244
bun.lock
244245

README.md

Lines changed: 34 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ So I built Pilot. Instead of adding process on top, it bakes quality into every
5050
| Every session starts fresh | Persistent memory across sessions via Pilot Console |
5151
| Hope it works | Verifier sub-agents perform code review before marking complete |
5252
| No codebase knowledge | Production-tested rules loaded into every session |
53-
| Generic suggestions | Coding skills activated dynamically when relevant |
53+
| Generic suggestions | Coding standards activated conditionally by file type |
5454
| Changes mixed into branch | Isolated worktrees — review and squash merge when verified |
5555
| Manual tool setup | MCP servers + language servers pre-configured and ready |
5656

@@ -97,7 +97,7 @@ After installation, run `pilot` or `ccp` in your project folder to start Claude
9797
1. **Prerequisites** — Checks Homebrew, Node.js, Python 3.12+, uv, git
9898
2. **Dependencies** — Installs Vexor, playwright-cli, mcp-cli, Claude Code
9999
3. **Shell integration** — Auto-configures bash, fish, and zsh with `pilot` alias
100-
4. **Config & Claude files** — Sets up `.claude/` plugin, rules, skills, hooks, MCP servers
100+
4. **Config & Claude files** — Sets up `.claude/` plugin, rules, commands, hooks, MCP servers
101101
5. **VS Code extensions** — Installs recommended extensions for your stack
102102
6. **Dev Container** — Auto-setup with all tools pre-configured
103103
7. **Automated updater** — Checks for updates on launch with release notes and one-key upgrade
@@ -118,9 +118,9 @@ curl -fsSL https://raw.githubusercontent.com/maxritter/claude-pilot/main/install
118118

119119
## How It Works
120120

121-
### /sync — Sync Rules & Skills
121+
### /sync — Sync Rules & Standards
122122

123-
Run `/sync` to sync custom rules and skills with your codebase. Explores your codebase, builds a semantic search index, discovers undocumented patterns, updates project documentation, and creates new skills. Run it once initially, then anytime again:
123+
Run `/sync` to sync rules and standards with your codebase. Explores your codebase, builds a semantic search index, discovers undocumented patterns, updates project documentation, and creates new custom skills. Run it once initially, then anytime again:
124124

125125
```bash
126126
pilot
@@ -133,13 +133,13 @@ pilot
133133
| Phase | Action |
134134
| ----- | --------------------------------------------------------------- |
135135
| 0 | Load reference guidelines, output locations, error handling |
136-
| 1 | Read existing rules and skills from `.claude/` |
136+
| 1 | Read existing rules and standards from `.claude/` |
137137
| 2 | Build Vexor semantic search index (first run may take 5-15 min) |
138138
| 3 | Explore codebase with Vexor/Grep to find patterns |
139139
| 4 | Compare discovered vs documented patterns |
140140
| 5 | Sync/update `project.md` with tech stack and commands |
141141
| 6 | Sync MCP server documentation |
142-
| 7 | Update existing skills that have changed |
142+
| 7 | Update existing custom skills that have changed |
143143
| 8 | Discover and document new undocumented patterns as rules |
144144
| 9 | Create new skills via `/learn` command |
145145
| 10 | Report summary of all changes |
@@ -300,13 +300,13 @@ All commands support `--json` for structured output. Multiple Pilot sessions can
300300

301301
Create your own in your project's `.claude/` folder:
302302

303-
| Type | Loaded | Best for |
304-
| ------------ | --------------------------------- | ---------------------------------------- |
305-
| **Rules** | Every session (always in context) | Guidelines Claude should always follow |
306-
| **Commands** | On demand via `/command` | Specific workflows or multi-step tasks |
307-
| **Skills** | Dynamically when relevant | Specialized knowledge for specific tasks |
303+
| Type | Loaded | Best for |
304+
| ------------ | ----------------------------------------------- | ---------------------------------------- |
305+
| **Rules** | Every session, or conditionally by file type | Guidelines Claude should always follow |
306+
| **Commands** | On demand via `/command` | Specific workflows or multi-step tasks |
307+
| **Skills** | On demand, created via `/learn` | Reusable knowledge from past sessions |
308308

309-
Claude Pilot automatically installs best-practice rules, commands, and coding standard skills.
309+
Claude Pilot automatically installs best-practice rules, commands, and coding standards. Standards rules use `paths` frontmatter to activate only when you're working with matching file types (e.g., Python standards load only when editing `.py` files). Custom skills are created by `/learn` when it detects non-obvious discoveries, workarounds, or reusable workflows — and can be shared across your team via `/vault`.
310310

311311
### Custom MCP Servers
312312

@@ -424,26 +424,25 @@ Production-tested best practices loaded into **every session**. These aren't sug
424424

425425
</details>
426426

427-
### Built-in Coding Skills
428-
429-
Dynamically activated when relevant — specialized knowledge loaded on demand:
430-
431-
| Skill | Coverage |
432-
| -------------------- | ---------------------------------------------------------------- |
433-
| Python Standards | uv, pytest, ruff, basedpyright, type hints, docstrings |
434-
| TypeScript Standards | npm/pnpm, Jest, ESLint, Prettier, React patterns |
435-
| Go Standards | Modules, testing, formatting, error handling |
436-
| Testing Patterns | Unit testing, integration testing, mocking, coverage goals |
437-
| Test Organization | File structure, naming conventions, fixtures, setup |
438-
| API Design | RESTful patterns, response envelopes, error handling, versioning |
439-
| Data Models | Database schemas, type safety, migrations, relationships |
440-
| Components | Reusable patterns, props design, documentation, testing |
441-
| CSS / Styling | Naming conventions, organization, responsive design, performance |
442-
| Responsive Design | Mobile-first, breakpoints, Flexbox/Grid, touch interactions |
443-
| Design System | Color palette, typography, spacing, component consistency |
444-
| Accessibility | WCAG compliance, ARIA attributes, keyboard nav, screen readers |
445-
| DB Migrations | Schema changes, data transformation, rollback strategy |
446-
| Query Optimization | Indexing, N+1 problems, query patterns, performance |
427+
### Built-in Coding Standards
428+
429+
Conditional rules activated by file type — loaded only when working with matching files:
430+
431+
| Standard | Activates On | Coverage |
432+
| -------------------- | ------------------------------- | ---------------------------------------------------------------- |
433+
| Python | `*.py` | uv, pytest, ruff, basedpyright, type hints, docstrings |
434+
| TypeScript | `*.ts`, `*.tsx`, `*.js`, `*.jsx`| npm/pnpm, Jest, ESLint, Prettier, React patterns |
435+
| Go | `*.go` | Modules, testing, formatting, error handling |
436+
| Testing Strategies | `*test*`, `*spec*` | Unit vs integration vs E2E, mocking, coverage goals |
437+
| API Design | `*route*`, `*endpoint*`, `*api*`| RESTful patterns, response envelopes, error handling, versioning |
438+
| Data Models | `*model*`, `*schema*`, `*entity*`| Database schemas, type safety, migrations, relationships |
439+
| Components | `*component*`, `*.tsx`, `*.vue` | Reusable patterns, props design, documentation, testing |
440+
| CSS / Styling | `*.css`, `*.scss`, `*.tailwind*`| Naming conventions, organization, responsive design, performance |
441+
| Responsive Design | `*.css`, `*.scss`, `*.tsx` | Mobile-first, breakpoints, Flexbox/Grid, touch interactions |
442+
| Design System | `*.css`, `*.tsx`, `*.vue` | Color palette, typography, spacing, component consistency |
443+
| Accessibility | `*.tsx`, `*.jsx`, `*.vue`, `*.html`| WCAG compliance, ARIA attributes, keyboard nav, screen readers |
444+
| DB Migrations | `*migration*`, `*alembic*` | Schema changes, data transformation, rollback strategy |
445+
| Query Optimization | `*query*`, `*repository*`, `*dao*`| Indexing, N+1 problems, query patterns, performance |
447446

448447
### MCP Servers
449448

@@ -537,21 +536,21 @@ Yes. Pilot enhances Claude Code — it doesn't replace it. You need an active Cl
537536
<details>
538537
<summary><b>Does Pilot work with any programming language?</b></summary>
539538

540-
Pilot's quality hooks (auto-formatting, linting, type checking) currently support Python, TypeScript/JavaScript, and Go out of the box. TDD enforcement, spec-driven development, Endless Mode, persistent memory, and all rules and skills work with any language that Claude Code supports. You can add custom hooks for additional languages.
539+
Pilot's quality hooks (auto-formatting, linting, type checking) currently support Python, TypeScript/JavaScript, and Go out of the box. TDD enforcement, spec-driven development, Endless Mode, persistent memory, and all rules and standards work with any language that Claude Code supports. You can add custom hooks for additional languages.
541540

542541
</details>
543542

544543
<details>
545544
<summary><b>Can I use Pilot on multiple projects?</b></summary>
546545

547-
Yes. Pilot installs once and works across all your projects. Each project can have its own `.claude/` rules, skills, and MCP servers. Run `/sync` in each project to generate project-specific documentation and skills.
546+
Yes. Pilot installs once and works across all your projects. Each project can have its own `.claude/` rules, custom skills, and MCP servers. Run `/sync` in each project to generate project-specific documentation and standards.
548547

549548
</details>
550549

551550
<details>
552551
<summary><b>Can I customize the rules and hooks?</b></summary>
553552

554-
Yes. All rules in `.claude/rules/` are markdown files you can edit, extend, or replace. Hooks are Python scripts you can modify. Skills are dynamically loaded and can be customized or created via `/learn`. Project-specific rules override global defaults. Use `/vault` to share customizations across your team.
553+
Yes. All rules in `.claude/rules/` are markdown files you can edit, extend, or replace. Hooks are Python scripts you can modify. Built-in coding standards are conditional rules that activate by file type and can be customized. You can also create custom skills via `/learn`. Project-specific rules override global defaults. Use `/vault` to share customizations across your team.
555554

556555
</details>
557556

console/src/services/worker-service.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ import { PlanRoutes } from "./worker/http/routes/PlanRoutes.js";
6666
import { WorktreeRoutes } from "./worker/http/routes/WorktreeRoutes.js";
6767
import { VexorRoutes } from "./worker/http/routes/VexorRoutes.js";
6868
import { LicenseRoutes } from "./worker/http/routes/LicenseRoutes.js";
69+
import { VaultRoutes } from "./worker/http/routes/VaultRoutes.js";
6970
import { MetricsService } from "./worker/MetricsService.js";
7071
import { startRetentionScheduler, stopRetentionScheduler } from "./worker/RetentionScheduler.js";
7172

@@ -251,6 +252,7 @@ export class WorkerService {
251252
this.server.registerRoutes(this.vexorRoutes);
252253

253254
this.server.registerRoutes(new LicenseRoutes());
255+
this.server.registerRoutes(new VaultRoutes());
254256

255257
startRetentionScheduler(this.dbManager);
256258
}
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
/**
2+
* VaultRoutes
3+
*
4+
* API endpoints for sx Team Vault status and management.
5+
* Invokes the sx CLI via Bun.spawn with timeout and caching.
6+
*/
7+
8+
import express, { type Request, type Response } from "express";
9+
import { BaseRouteHandler } from "../BaseRouteHandler.js";
10+
import { logger } from "../../../../utils/logger.js";
11+
12+
export interface VaultAsset {
13+
name: string;
14+
version: string;
15+
type: string;
16+
clients: string[];
17+
status: string;
18+
scope: string;
19+
}
20+
21+
export interface VaultCatalogItem {
22+
name: string;
23+
type: string;
24+
latestVersion: string;
25+
versionsCount: number;
26+
updatedAt: string;
27+
}
28+
29+
export interface VaultStatus {
30+
installed: boolean;
31+
version: string | null;
32+
configured: boolean;
33+
vaultUrl: string | null;
34+
profile: string | null;
35+
assets: VaultAsset[];
36+
catalog: VaultCatalogItem[];
37+
isInstalling: boolean;
38+
}
39+
40+
const STATUS_TIMEOUT_MS = 15_000;
41+
const INSTALL_TIMEOUT_MS = 60_000;
42+
const STATUS_CACHE_TTL_MS = 30_000;
43+
44+
export class VaultRoutes extends BaseRouteHandler {
45+
private statusCache: { data: VaultStatus; timestamp: number } | null = null;
46+
private _isInstalling = false;
47+
48+
setupRoutes(app: express.Application): void {
49+
app.get("/api/vault/status", this.handleStatus.bind(this));
50+
app.post("/api/vault/install", this.handleInstall.bind(this));
51+
}
52+
53+
private handleStatus = this.wrapHandler(async (_req: Request, res: Response): Promise<void> => {
54+
if (this.statusCache && Date.now() - this.statusCache.timestamp < STATUS_CACHE_TTL_MS) {
55+
res.json({ ...this.statusCache.data, isInstalling: this._isInstalling });
56+
return;
57+
}
58+
59+
const sxPath = this.resolveSxBinary();
60+
if (!sxPath) {
61+
res.json(this.emptyStatus());
62+
return;
63+
}
64+
65+
try {
66+
const [configOutput, catalogOutput] = await Promise.all([
67+
this.runSxCommand([sxPath, "config", "--json"], STATUS_TIMEOUT_MS),
68+
this.runSxCommand([sxPath, "vault", "list", "--json"], STATUS_TIMEOUT_MS).catch(() => "[]"),
69+
]);
70+
71+
const config = JSON.parse(configOutput);
72+
const catalog: VaultCatalogItem[] = JSON.parse(catalogOutput).map((item: any) => ({
73+
name: item.name,
74+
type: item.type,
75+
latestVersion: item.latestVersion,
76+
versionsCount: item.versionsCount,
77+
updatedAt: item.updatedAt,
78+
}));
79+
80+
const assets: VaultAsset[] = [];
81+
for (const scopeGroup of config.assets || []) {
82+
const scope = scopeGroup.scope || "Global";
83+
for (const asset of scopeGroup.assets || []) {
84+
assets.push({
85+
name: asset.name,
86+
version: asset.version,
87+
type: asset.type,
88+
clients: asset.clients || [],
89+
status: asset.status || "unknown",
90+
scope,
91+
});
92+
}
93+
}
94+
95+
const status: VaultStatus = {
96+
installed: true,
97+
version: config.version?.version || null,
98+
configured: !!config.config?.repositoryUrl,
99+
vaultUrl: config.config?.repositoryUrl || null,
100+
profile: config.config?.profile || null,
101+
assets,
102+
catalog,
103+
isInstalling: this._isInstalling,
104+
};
105+
106+
this.statusCache = { data: status, timestamp: Date.now() };
107+
res.json(status);
108+
} catch (error) {
109+
logger.error("HTTP", "Vault status failed", {}, error as Error);
110+
res.json(this.emptyStatus());
111+
}
112+
});
113+
114+
private handleInstall = this.wrapHandler(async (_req: Request, res: Response): Promise<void> => {
115+
if (this._isInstalling) {
116+
res.status(409).json({ error: "Installation already in progress" });
117+
return;
118+
}
119+
120+
const sxPath = this.resolveSxBinary();
121+
if (!sxPath) {
122+
res.status(500).json({ error: "sx CLI not found" });
123+
return;
124+
}
125+
126+
this._isInstalling = true;
127+
this.statusCache = null;
128+
res.json({ started: true });
129+
130+
try {
131+
await this.runSxCommand([sxPath, "install", "--repair"], INSTALL_TIMEOUT_MS);
132+
logger.info("HTTP", "Vault install --repair completed");
133+
} catch (error) {
134+
logger.error("HTTP", "Vault install failed", {}, error as Error);
135+
} finally {
136+
this._isInstalling = false;
137+
this.statusCache = null;
138+
}
139+
});
140+
141+
private emptyStatus(): VaultStatus {
142+
return {
143+
installed: false,
144+
version: null,
145+
configured: false,
146+
vaultUrl: null,
147+
profile: null,
148+
assets: [],
149+
catalog: [],
150+
isInstalling: this._isInstalling,
151+
};
152+
}
153+
154+
private resolveSxBinary(): string | null {
155+
const found = Bun.which("sx");
156+
return found || null;
157+
}
158+
159+
private async runSxCommand(args: string[], timeoutMs: number): Promise<string> {
160+
const proc = Bun.spawn(args, {
161+
stdout: "pipe",
162+
stderr: "pipe",
163+
});
164+
165+
const timeoutId = setTimeout(() => {
166+
try {
167+
proc.kill("SIGTERM");
168+
setTimeout(() => { try { proc.kill("SIGKILL"); } catch {} }, 1000);
169+
} catch {}
170+
}, timeoutMs);
171+
172+
try {
173+
const [stdout, stderr] = await Promise.all([
174+
new Response(proc.stdout).text(),
175+
new Response(proc.stderr).text(),
176+
]);
177+
const exitCode = await proc.exited;
178+
179+
if (exitCode !== 0) {
180+
throw new Error(`sx exited with code ${exitCode}: ${stderr.slice(0, 200)}`);
181+
}
182+
183+
return stdout;
184+
} finally {
185+
clearTimeout(timeoutId);
186+
}
187+
}
188+
}

0 commit comments

Comments
 (0)