pi-squad 0.6.5 → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-squad",
3
- "version": "0.6.5",
3
+ "version": "0.7.2",
4
4
  "description": "Multi-agent collaboration extension for pi — task decomposition, dependency management, parallel execution, TUI panel",
5
5
  "type": "module",
6
6
  "pi": {
@@ -8,7 +8,12 @@
8
8
  "src/index.ts"
9
9
  ],
10
10
  "skills": [
11
- "src/skills/squad-supervisor"
11
+ "src/skills/squad-supervisor",
12
+ "src/skills/squad-backend-dev",
13
+ "src/skills/squad-frontend-dev",
14
+ "src/skills/squad-qa-testing",
15
+ "src/skills/squad-security-audit",
16
+ "src/skills/squad-architecture"
12
17
  ]
13
18
  },
14
19
  "files": [
package/src/index.ts CHANGED
@@ -352,14 +352,15 @@ export default function (pi: ExtensionAPI) {
352
352
  switch (event.type) {
353
353
  case "squad_completed": {
354
354
  const tasks = store.loadAllTasks(squadId);
355
+ const summary = tasks
356
+ .filter((t) => t.status === "done")
357
+ .map((t) => `- ${t.id} (${t.agent}): ${t.output?.slice(0, 150) || "done"}`)
358
+ .join("\n");
355
359
  const totalCost = tasks.reduce((sum, t) => sum + t.usage.cost, 0);
356
360
  const s = schedulers.get(squadId); if (s) s.updateContext();
357
- const overview = store.loadOverview(squadId);
358
361
  pi.sendMessage({
359
362
  customType: "squad-completed",
360
- content: `[squad] Squad "${squadId}" completed all ${tasks.length} tasks.\n\n` +
361
- (overview ? `## Squad Overview\n\n${overview}\n\n` : "") +
362
- `Total cost: $${totalCost.toFixed(4)}`,
363
+ content: `[squad] Squad "${squadId}" completed all ${tasks.length} tasks.\n\nSummary:\n${summary}\n\nTotal cost: $${totalCost.toFixed(4)}`,
363
364
  display: true,
364
365
  });
365
366
  schedulers.delete(squadId);
@@ -370,12 +371,9 @@ export default function (pi: ExtensionAPI) {
370
371
  const tasks = store.loadAllTasks(squadId);
371
372
  const failed = tasks.filter((t) => t.status === "failed");
372
373
  const done = tasks.filter((t) => t.status === "done");
373
- const overview = store.loadOverview(squadId);
374
374
  pi.sendMessage({
375
375
  customType: "squad-failed",
376
- content: `[squad] Squad "${squadId}" has stalled. ${done.length}/${tasks.length} done, ${failed.length} failed.\n` +
377
- `Failed: ${failed.map((t) => `${t.id}: ${t.error?.slice(0, 100)}`).join("; ")}` +
378
- (overview ? `\n\n## Squad Overview\n\n${overview}` : ""),
376
+ content: `[squad] Squad "${squadId}" has stalled. ${done.length}/${tasks.length} done, ${failed.length} failed.\nFailed: ${failed.map((t) => `${t.id}: ${t.error?.slice(0, 100)}`).join("; ")}`,
379
377
  display: true,
380
378
  }, { triggerTurn: true });
381
379
  forceWidgetUpdate();
@@ -1229,31 +1227,6 @@ async function startSquad(
1229
1227
 
1230
1228
  store.saveSquad(squad);
1231
1229
 
1232
- // Create initial OVERVIEW.md with squad goal, task plan, and design contract
1233
- const planLines = [
1234
- `# Squad: ${params.goal}`,
1235
- ``,
1236
- `**Created:** ${squad.created}`,
1237
- `**Tasks:** ${plan.tasks.length}`,
1238
- ``,
1239
- `## Task Plan`,
1240
- ``,
1241
- ...plan.tasks.map((t) => {
1242
- const deps = t.depends.length > 0 ? ` (after: ${t.depends.join(", ")})` : "";
1243
- return `- **${t.id}** → ${t.agent}: ${t.title}${deps}`;
1244
- }),
1245
- ``,
1246
- ];
1247
-
1248
- // Extract design contract from task descriptions — API paths, schemas,
1249
- // ports, file conventions — so parallel agents share a single source of truth.
1250
- const contractLines = buildDesignContract(plan.tasks, params.goal);
1251
- if (contractLines.length > 0) {
1252
- planLines.push(...contractLines);
1253
- }
1254
-
1255
- store.appendOverview(squadId, planLines.join("\n"));
1256
-
1257
1230
  // Create task files
1258
1231
  for (const taskDef of plan.tasks) {
1259
1232
  const task: Task = {
@@ -1301,6 +1274,10 @@ async function startSquad(
1301
1274
  switch (event.type) {
1302
1275
  case "squad_completed": {
1303
1276
  const tasks = store.loadAllTasks(squadId);
1277
+ const summary = tasks
1278
+ .filter((t) => t.status === "done")
1279
+ .map((t) => `- ${t.id} (${t.agent}): ${t.output?.slice(0, 150) || "done"}`)
1280
+ .join("\n");
1304
1281
  const totalCost = tasks.reduce((sum, t) => sum + t.usage.cost, 0);
1305
1282
 
1306
1283
  // Final context update before clearing scheduler
@@ -1309,17 +1286,10 @@ async function startSquad(
1309
1286
  completedSched.updateContext();
1310
1287
  }
1311
1288
 
1312
- // Load the full overview document — contains the narrative of
1313
- // each task's output, decisions, issues, and files modified.
1314
- const overview = store.loadOverview(squadId);
1315
-
1316
- // Send into LLM context (not display-only) so the main agent
1317
- // knows exactly what happened. No triggerTurn — user decides
1318
- // what to do next.
1319
1289
  pi.sendMessage({
1320
1290
  customType: "squad-completed",
1321
1291
  content: `[squad] Squad "${squadId}" completed all ${tasks.length} tasks.\n\n` +
1322
- (overview ? `## Squad Overview\n\n${overview}\n\n` : "") +
1292
+ `Summary:\n${summary}\n\n` +
1323
1293
  `Total cost: $${totalCost.toFixed(4)}`,
1324
1294
  display: true,
1325
1295
  });
@@ -1334,14 +1304,12 @@ async function startSquad(
1334
1304
  const tasks = store.loadAllTasks(squadId);
1335
1305
  const failed = tasks.filter((t) => t.status === "failed");
1336
1306
  const done = tasks.filter((t) => t.status === "done");
1337
- const overview = store.loadOverview(squadId);
1338
1307
 
1339
1308
  pi.sendMessage({
1340
1309
  customType: "squad-failed",
1341
1310
  content: `[squad] Squad "${squadId}" has stalled. ` +
1342
1311
  `${done.length}/${tasks.length} tasks done, ${failed.length} failed.\n` +
1343
1312
  `Failed: ${failed.map((t) => `${t.id}: ${t.error?.slice(0, 100)}`).join("; ")}\n` +
1344
- (overview ? `\n## Squad Overview\n\n${overview}\n\n` : "\n") +
1345
1313
  `Use squad_status for details or squad_modify to adjust.`,
1346
1314
  display: true,
1347
1315
  }, { triggerTurn: true });
@@ -1403,98 +1371,4 @@ function getSquadSkillPaths(skillsDir: string): string[] {
1403
1371
  .filter((dir) => fs.existsSync(path.join(dir, "SKILL.md")));
1404
1372
  }
1405
1373
 
1406
- /**
1407
- * Extract a design contract from task descriptions.
1408
- *
1409
- * Scans all tasks for API paths, ports, file names, data schemas, and
1410
- * shared conventions. Produces a "## Design Contract" section in the
1411
- * OVERVIEW.md so that ALL agents (including parallel ones) share a
1412
- * single source of truth before they start working.
1413
- */
1414
- function buildDesignContract(
1415
- tasks: Array<{ id: string; title: string; description: string; agent: string; depends: string[] }>,
1416
- goal: string,
1417
- ): string[] {
1418
- const lines: string[] = [];
1419
-
1420
- // Collect API routes mentioned in any task description
1421
- const apiRoutes: string[] = [];
1422
- const ports: string[] = [];
1423
- const files: string[] = [];
1424
- const schemas: string[] = [];
1425
-
1426
- const allText = tasks.map((t) => `${t.title}\n${t.description}`).join("\n") + "\n" + goal;
1427
-
1428
- // Extract API paths like GET /foo, POST /bar/:id
1429
- const routePattern = /\b(GET|POST|PUT|PATCH|DELETE|HEAD)\s+(\/[\w\/:]+)/gi;
1430
- for (const match of allText.matchAll(routePattern)) {
1431
- const route = `${match[1].toUpperCase()} ${match[2]}`;
1432
- if (!apiRoutes.includes(route)) apiRoutes.push(route);
1433
- }
1434
-
1435
- // Extract port numbers
1436
- const portPattern = /\b(?:port|PORT|Port)\s*[=:]?\s*(\d{4,5})\b/gi;
1437
- for (const match of allText.matchAll(portPattern)) {
1438
- if (!ports.includes(match[1])) ports.push(match[1]);
1439
- }
1440
-
1441
- // Extract key file names mentioned (e.g., server.js, index.html)
1442
- const filePattern = /\b([\w-]+\.(js|ts|json|html|css|sh|mjs|cjs))\b/gi;
1443
- for (const match of allText.matchAll(filePattern)) {
1444
- const f = match[1];
1445
- if (!files.includes(f) && !['package.json'].includes(f)) files.push(f);
1446
- }
1447
-
1448
- // Extract data schemas like {field, field, field}
1449
- const schemaPattern = /\{([a-zA-Z_][\w,\s\[\]?]+)\}/g;
1450
- for (const match of allText.matchAll(schemaPattern)) {
1451
- const fields = match[1].trim();
1452
- if (fields.includes(',') && fields.length > 5 && fields.length < 200) {
1453
- if (!schemas.includes(fields)) schemas.push(fields);
1454
- }
1455
- }
1456
-
1457
- // Only emit a contract section if we found shared design elements
1458
- if (apiRoutes.length === 0 && ports.length === 0 && schemas.length === 0) {
1459
- return [];
1460
- }
1461
-
1462
- lines.push(`## Design Contract`);
1463
- lines.push(``);
1464
- lines.push(`> **All agents MUST follow these specifications.** Do not invent`);
1465
- lines.push(`> alternative paths, ports, or schemas. If you need to deviate,`);
1466
- lines.push(`> document the reason in your output.`);
1467
- lines.push(``);
1468
-
1469
- if (ports.length > 0) {
1470
- lines.push(`### Server`);
1471
- lines.push(`- Port: **${ports.join(", ")}**`);
1472
- lines.push(``);
1473
- }
1474
-
1475
- if (apiRoutes.length > 0) {
1476
- lines.push(`### API Endpoints`);
1477
- for (const r of apiRoutes) {
1478
- lines.push(`- \`${r}\``);
1479
- }
1480
- lines.push(``);
1481
- }
1482
1374
 
1483
- if (schemas.length > 0) {
1484
- lines.push(`### Data Schemas`);
1485
- for (const s of schemas) {
1486
- lines.push(`- \`{ ${s} }\``);
1487
- }
1488
- lines.push(``);
1489
- }
1490
-
1491
- if (files.length > 0) {
1492
- lines.push(`### Key Files`);
1493
- for (const f of files) {
1494
- lines.push(`- \`${f}\``);
1495
- }
1496
- lines.push(``);
1497
- }
1498
-
1499
- return lines;
1500
- }
package/src/protocol.ts CHANGED
@@ -11,7 +11,7 @@
11
11
  */
12
12
 
13
13
  import type { AgentDef, KnowledgeEntry, Squad, Task, TaskMessage } from "./types.js";
14
- import { loadAllKnowledge, loadAllTasks, loadMessages, loadOverview } from "./store.js";
14
+ import { loadAllKnowledge, loadAllTasks, loadMessages } from "./store.js";
15
15
 
16
16
  // ============================================================================
17
17
  // Squad Protocol (injected into every agent)
@@ -54,9 +54,7 @@ The squad system will detect this and route help.
54
54
  ## Rules
55
55
  - Stay focused on YOUR task — don't do work assigned to other agents
56
56
  - Read the dependency outputs below — don't redo completed work
57
- - **Follow the Design Contract in the Squad Progress Document** — use the exact API paths, ports, schemas, and file names specified. Do NOT invent alternatives
58
57
  - Check the modified files list — coordinate before editing shared files
59
- - When creating APIs, clearly document all endpoints, request/response shapes, and status codes in your completion output
60
58
  - Ask for help if stuck — don't spin for more than a few minutes
61
59
  - Verify your work before claiming done
62
60
  `;
@@ -116,20 +114,6 @@ ${sections.join("\n---\n\n")}
116
114
  `;
117
115
  }
118
116
 
119
- // ============================================================================
120
- // Squad Progress Overview
121
- // ============================================================================
122
-
123
- export function buildOverviewSection(squadId: string): string {
124
- const content = loadOverview(squadId);
125
- if (!content.trim()) return "";
126
-
127
- return `# Squad Progress Document
128
-
129
- ${content.trim()}
130
- `;
131
- }
132
-
133
117
  // ============================================================================
134
118
  // Sibling Awareness
135
119
  // ============================================================================
@@ -309,7 +293,6 @@ export function buildAgentSystemPrompt(options: ProtocolBuildOptions): string {
309
293
  buildTaskSection(task),
310
294
  buildReworkContext(task, squadId),
311
295
  buildChainContext(task, allTasks, squadId),
312
- buildOverviewSection(squadId),
313
296
  buildSiblingAwareness(task, allTasks, modifiedFiles),
314
297
  buildKnowledgeSection(squadId),
315
298
  buildQueuedMessages(queuedMessages),
package/src/scheduler.ts CHANGED
@@ -463,10 +463,6 @@ export class Scheduler {
463
463
  text: "Task completed",
464
464
  });
465
465
 
466
- // Reload task after status update so overview has output, completed time, etc.
467
- const updatedTask = store.loadTask(this.squadId, taskId) || task;
468
- this.appendTaskOverview(updatedTask, taskId, messages);
469
-
470
466
  this.emit({
471
467
  type: "task_completed",
472
468
  squadId: this.squadId,
@@ -943,88 +939,6 @@ export class Scheduler {
943
939
  return textParts.length > 0 ? textParts.join("\n") : null;
944
940
  }
945
941
 
946
- // =========================================================================
947
- // Overview Document — append task summary after completion
948
- // =========================================================================
949
-
950
- /**
951
- * Build a concise markdown summary of a completed task and append it
952
- * to the squad's OVERVIEW.md. This gives subsequent agents a narrative
953
- * understanding of what was accomplished, issues hit, and decisions made.
954
- */
955
- private appendTaskOverview(
956
- task: Task,
957
- taskId: string,
958
- messages: import("./types.js").TaskMessage[],
959
- ): void {
960
- try {
961
- const lines: string[] = [];
962
-
963
- // Header
964
- lines.push(`## ${task.id}: ${task.title}`);
965
- lines.push(``);
966
- lines.push(`**Agent:** ${task.agent} | **Status:** ${task.status}`);
967
- if (task.started && task.completed) {
968
- const dur = new Date(task.completed).getTime() - new Date(task.started).getTime();
969
- lines.push(`**Duration:** ${formatElapsed(dur)}`);
970
- }
971
- lines.push(``);
972
-
973
- // Output
974
- if (task.output) {
975
- lines.push(`### Output`);
976
- lines.push(task.output.slice(0, 800));
977
- if (task.output.length > 800) lines.push(`... (truncated)`);
978
- lines.push(``);
979
- }
980
-
981
- // Issues / errors encountered
982
- const errors = messages.filter((m) => m.type === "error" && m.from !== "system");
983
- if (errors.length > 0) {
984
- lines.push(`### Issues Encountered`);
985
- for (const err of errors.slice(-5)) {
986
- lines.push(`- ${err.text.split("\n")[0].slice(0, 200)}`);
987
- }
988
- lines.push(``);
989
- }
990
-
991
- // Decisions — scan agent text for decision-like language
992
- const decisionPatterns = /\b(decided|chose|approach|instead of|trade-?off|opted|going with|switched to|using .+ because)\b/i;
993
- const agentTexts = messages.filter((m) => m.from === task.agent && m.type === "text");
994
- const decisions: string[] = [];
995
- for (const msg of agentTexts) {
996
- for (const line of msg.text.split("\n")) {
997
- if (decisionPatterns.test(line) && line.trim().length > 10) {
998
- decisions.push(line.trim().slice(0, 200));
999
- }
1000
- }
1001
- }
1002
- if (decisions.length > 0) {
1003
- lines.push(`### Decisions`);
1004
- for (const d of decisions.slice(-5)) {
1005
- lines.push(`- ${d}`);
1006
- }
1007
- lines.push(``);
1008
- }
1009
-
1010
- // Files modified
1011
- const activity = this.pool.getActivity(taskId);
1012
- if (activity && activity.modifiedFiles.size > 0) {
1013
- lines.push(`### Files Modified`);
1014
- for (const f of Array.from(activity.modifiedFiles).slice(0, 15)) {
1015
- lines.push(`- ${f}`);
1016
- }
1017
- if (activity.modifiedFiles.size > 15) {
1018
- lines.push(`- ... and ${activity.modifiedFiles.size - 15} more`);
1019
- }
1020
- lines.push(``);
1021
- }
1022
-
1023
- store.appendOverview(this.squadId, lines.join("\n"));
1024
- } catch (err) {
1025
- logError("squad-scheduler", `Failed to append overview for ${taskId}: ${(err as Error).message}`);
1026
- }
1027
- }
1028
942
  }
1029
943
 
1030
944
  function formatElapsed(ms: number): string {
@@ -0,0 +1,53 @@
1
+ ---
2
+ name: squad-architecture
3
+ description: >
4
+ System architecture practices — project structure, API contracts, shared types,
5
+ monorepo setup, and technical decision documentation. Use when designing system
6
+ architecture, defining contracts between components, or setting up project structure.
7
+ version: 1.0.0
8
+ ---
9
+
10
+ # Architecture & System Design
11
+
12
+ ## Project Structure
13
+ - Define clear boundaries between components (backend, frontend, shared)
14
+ - Use a monorepo with workspaces when frontend and backend share types
15
+ - Create a shared types/constants package that both sides import
16
+ - Document the project structure in a README or ARCHITECTURE.md
17
+
18
+ ## API Contract Definition
19
+ When defining API contracts that other agents will implement:
20
+ - List EVERY endpoint with method, path, request body, and response shape
21
+ - Specify exact field names, types, and which fields are optional
22
+ - Define error response format consistently
23
+ - Specify authentication requirements per endpoint
24
+ - Include example request/response pairs
25
+
26
+ Example:
27
+ ```
28
+ POST /api/auth/login
29
+ Request: { email: string, password: string }
30
+ Response: { user: { id, email, name }, accessToken: string, refreshToken: string }
31
+ Errors: 401 { error: "Invalid credentials" }
32
+ ```
33
+
34
+ ## Shared Types
35
+ - Define TypeScript interfaces for all data models
36
+ - Include validation schemas (zod) alongside types
37
+ - Export constants (status enums, priority levels, config values)
38
+ - Version the shared package so consumers know when contracts change
39
+
40
+ ## Technical Decisions
41
+ Document every significant decision in your output:
42
+ - What was decided and why
43
+ - What alternatives were considered
44
+ - What trade-offs were accepted
45
+
46
+ This helps downstream agents understand the rationale and stay consistent.
47
+
48
+ ## Handoff Quality
49
+ Your output is the contract that all other agents build against. Be precise:
50
+ - Don't leave ambiguity in field names or types
51
+ - Specify exact port numbers, file paths, directory structure
52
+ - Include the database schema with column types and constraints
53
+ - List all environment variables needed
@@ -0,0 +1,45 @@
1
+ ---
2
+ name: squad-backend-dev
3
+ description: >
4
+ Backend engineering practices — API design, database patterns, auth implementation,
5
+ input validation, error handling, and security. Use when building APIs, servers,
6
+ databases, or backend services.
7
+ version: 1.0.0
8
+ ---
9
+
10
+ # Backend Development
11
+
12
+ ## API Design
13
+ - RESTful conventions: GET (read), POST (create), PUT (replace), PATCH (update), DELETE (remove)
14
+ - Consistent response format: success returns data directly, errors return `{ error: string, code?: string }`
15
+ - Validate all inputs at the boundary (use zod, joi, or manual checks)
16
+ - Paginate list endpoints (limit/offset or cursor-based)
17
+ - Use proper HTTP status codes: 200 OK, 201 Created, 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 409 Conflict, 500 Server Error
18
+ - Document every endpoint in your completion output (method, path, request/response shape)
19
+
20
+ ## Database
21
+ - Use migrations for schema changes (never ALTER in application code)
22
+ - Add indexes for frequently queried columns and foreign keys
23
+ - Use foreign keys with appropriate ON DELETE behavior (CASCADE, SET NULL)
24
+ - Use transactions for multi-step writes
25
+ - Sanitize all user inputs in queries (parameterized queries, never string interpolation)
26
+
27
+ ## Authentication
28
+ - Never store passwords in plain text — use bcrypt with sufficient rounds (10+)
29
+ - JWT access tokens: short-lived (15min), stateless verification
30
+ - Refresh tokens: longer-lived (7d), stored server-side, rotated on use
31
+ - Validate tokens on every protected endpoint via middleware
32
+ - Return 401 for invalid/expired tokens, 403 for insufficient permissions
33
+
34
+ ## Error Handling
35
+ - Catch errors at route level, don't let unhandled rejections crash the server
36
+ - Log errors with context (request id, user id, endpoint)
37
+ - Never expose stack traces or internal details in API responses
38
+ - Use typed error classes for different error categories
39
+ - Implement graceful shutdown (close DB connections, finish in-flight requests)
40
+
41
+ ## Security
42
+ - Rate-limit public endpoints (login, register, password reset)
43
+ - Set security headers (CORS, Helmet for Express)
44
+ - Validate file uploads (type whitelist, size limits)
45
+ - Never log sensitive data (passwords, tokens, PII)
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: collaboration
2
+ name: squad-collaboration
3
3
  description: Multi-agent collaboration patterns — how to build on others' work, ask questions, share knowledge, and work as a team.
4
4
  ---
5
5
 
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: squad-frontend-dev
3
+ description: >
4
+ Frontend engineering practices — React patterns, CSS/Tailwind, accessibility,
5
+ state management, API integration, and responsive design. Use when building
6
+ UIs, web apps, or frontend components.
7
+ version: 1.0.0
8
+ ---
9
+
10
+ # Frontend Development
11
+
12
+ ## React Patterns
13
+ - Use functional components with hooks (no class components)
14
+ - Extract reusable logic into custom hooks (useAuth, useFetch, useDebounce)
15
+ - Handle all UI states explicitly: loading, error, empty, success
16
+ - Use React.memo only for measured performance bottlenecks
17
+ - Prefer composition over prop drilling — use context for cross-cutting concerns
18
+ - Use controlled components for forms, validate before submit
19
+
20
+ ## State Management
21
+ - Server state: use React Query / TanStack Query (caching, refetching, optimistic updates)
22
+ - Client state: use useState for local, useContext for shared, useReducer for complex
23
+ - URL state: use router params/search params for bookmarkable state
24
+ - Never duplicate server state in client state — let the query cache be the source of truth
25
+
26
+ ## API Integration
27
+ - Create a typed API client module (don't scatter fetch calls across components)
28
+ - Handle 401 responses globally (refresh token, redirect to login)
29
+ - Show loading indicators for any request > 200ms
30
+ - Handle network errors gracefully (offline banner, retry button)
31
+ - Use optimistic updates for snappy UX (revert on error)
32
+
33
+ ## CSS / Tailwind
34
+ - Use utility classes, avoid custom CSS when possible
35
+ - Follow the project's design tokens (colors, spacing, typography)
36
+ - Use responsive prefixes: sm:, md:, lg:, xl:
37
+ - Implement dark mode with dark: prefix when required
38
+ - Ensure consistent spacing scale (don't mix arbitrary values)
39
+
40
+ ## Accessibility
41
+ - All interactive elements must be keyboard-navigable (tab, enter, escape)
42
+ - Use semantic HTML elements (button, nav, main, section, header, footer)
43
+ - Add aria-labels to icon-only buttons and non-text interactive elements
44
+ - Ensure color contrast meets WCAG AA (4.5:1 for normal text, 3:1 for large)
45
+ - Support screen readers: announce dynamic content changes with aria-live
46
+
47
+ ## Build & Performance
48
+ - Verify the build completes without errors before claiming done
49
+ - Code-split routes (React.lazy + Suspense)
50
+ - Optimize images (lazy loading, proper sizing)
51
+ - Minimize bundle size (check for unnecessary dependencies)
@@ -0,0 +1,61 @@
1
+ ---
2
+ name: squad-qa-testing
3
+ description: >
4
+ QA and testing practices — test strategy, checklist, evidence requirements,
5
+ verdict format, and rework flow. Use when verifying, testing, or reviewing
6
+ implementations.
7
+ version: 1.0.0
8
+ ---
9
+
10
+ # QA & Testing
11
+
12
+ ## Test Strategy
13
+ 1. **Build verification**: Does the code compile/build without errors?
14
+ 2. **Smoke test**: Does the app start and respond to basic requests?
15
+ 3. **Functional tests**: Do all features work as specified?
16
+ 4. **Edge cases**: Invalid inputs, empty states, boundary values
17
+ 5. **Integration**: Do components work together (API ↔ frontend, auth flow)?
18
+
19
+ ## Before You Start
20
+ - Read the task description and dependency outputs carefully
21
+ - Understand what was built before testing it
22
+ - Start the server/app and verify it's actually running
23
+ - Don't assume anything works — verify everything
24
+
25
+ ## Testing Checklist
26
+ - [ ] App builds without errors (tsc, vite build, etc.)
27
+ - [ ] Server starts and responds to health check
28
+ - [ ] All CRUD operations work (create, read, update, delete)
29
+ - [ ] Authentication flow works (register, login, protected routes)
30
+ - [ ] Input validation rejects bad data (missing fields, wrong types)
31
+ - [ ] Error responses have correct HTTP status codes
32
+ - [ ] Frontend renders without console errors
33
+ - [ ] Navigation between pages works
34
+ - [ ] Forms submit correctly and show feedback
35
+
36
+ ## Evidence Requirements
37
+ Every claim must have evidence. Don't just say "it works" — show it:
38
+ - **API tests**: Show curl commands and their responses
39
+ - **Build tests**: Show the build command output (exit code 0)
40
+ - **UI tests**: Describe what you see, or use screenshots
41
+ - **Error tests**: Show the error response for invalid input
42
+
43
+ ## Verdict Format
44
+ ```
45
+ ## Verdict: PASS | FAIL
46
+
47
+ ### Issues Found
48
+ | # | Issue | Severity | Details |
49
+ |---|-------|----------|---------|
50
+ | 1 | ... | Critical/High/Medium/Low | ... |
51
+
52
+ ### Evidence
53
+ [test output, curl commands, screenshots]
54
+ ```
55
+
56
+ ## Rework Flow
57
+ If issues are found:
58
+ 1. Document each issue with severity, location, and reproduction steps
59
+ 2. The squad system will create fix tasks automatically
60
+ 3. You will re-test after fixes are applied
61
+ 4. On re-test: verify ALL previous issues are fixed, not just the latest
@@ -0,0 +1,43 @@
1
+ ---
2
+ name: squad-security-audit
3
+ description: >
4
+ Security audit checklist, vulnerability patterns, and remediation guidance.
5
+ Use when reviewing code for security issues, hardening an application,
6
+ or performing security verification.
7
+ version: 1.0.0
8
+ ---
9
+
10
+ # Security Audit
11
+
12
+ ## Checklist
13
+ - [ ] No secrets in source code (API keys, passwords, tokens, connection strings)
14
+ - [ ] All user inputs validated and sanitized
15
+ - [ ] SQL injection prevention (parameterized queries, no string interpolation)
16
+ - [ ] XSS prevention (output encoding, CSP headers, no innerHTML with user data)
17
+ - [ ] Authentication on all protected endpoints
18
+ - [ ] Authorization checks (can THIS user perform THIS action on THIS resource?)
19
+ - [ ] Rate limiting on public endpoints (login, register, password reset)
20
+ - [ ] Secure headers configured (CORS, HSTS, X-Frame-Options, X-Content-Type-Options)
21
+ - [ ] File upload validation (type whitelist, size limits)
22
+ - [ ] Error messages don't leak internal details (stack traces, SQL errors, file paths)
23
+ - [ ] Passwords hashed with bcrypt (not MD5, SHA1, or plain text)
24
+ - [ ] JWT tokens validated on every request (signature, expiry, issuer)
25
+ - [ ] Sensitive data not logged (passwords, tokens, credit cards)
26
+ - [ ] Dependencies checked for known vulnerabilities (npm audit)
27
+
28
+ ## Common Vulnerabilities
29
+ - **Broken Access Control**: Missing auth checks, IDOR (accessing other users' data by changing IDs)
30
+ - **Injection**: SQL, NoSQL, command injection via unsanitized inputs
31
+ - **Broken Auth**: Weak passwords allowed, no rate limiting on login, tokens never expire
32
+ - **Security Misconfiguration**: Default credentials, verbose error pages, unnecessary features enabled
33
+ - **Sensitive Data Exposure**: Secrets in client-side code, PII in logs, HTTP instead of HTTPS
34
+
35
+ ## Reporting Format
36
+ ```
37
+ ## Security Finding: [Title]
38
+ **Severity**: Critical | High | Medium | Low
39
+ **Location**: [file:line or endpoint]
40
+ **Description**: What's wrong
41
+ **Impact**: What could happen if exploited
42
+ **Remediation**: How to fix it (specific code change)
43
+ ```
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: verification
2
+ name: squad-verification
3
3
  description: Verify work before claiming completion — evidence-based discipline for multi-agent handoffs.
4
4
  ---
5
5
 
package/src/store.ts CHANGED
@@ -405,32 +405,6 @@ export function loadAllKnowledge(squadId: string): KnowledgeEntry[] {
405
405
  ].sort((a, b) => a.ts.localeCompare(b.ts));
406
406
  }
407
407
 
408
- // ============================================================================
409
- // Overview Document (shared squad summary)
410
- // ============================================================================
411
-
412
- export function getOverviewPath(squadId: string): string {
413
- return path.join(getSquadDir(squadId), "OVERVIEW.md");
414
- }
415
-
416
- export function loadOverview(squadId: string): string {
417
- try {
418
- return fs.readFileSync(getOverviewPath(squadId), "utf-8");
419
- } catch {
420
- return "";
421
- }
422
- }
423
-
424
- export function appendOverview(squadId: string, section: string): void {
425
- const filePath = getOverviewPath(squadId);
426
- ensureDir(path.dirname(filePath));
427
- const existing = loadOverview(squadId);
428
- const content = existing
429
- ? existing.trimEnd() + "\n\n---\n\n" + section.trim() + "\n"
430
- : section.trim() + "\n";
431
- fs.writeFileSync(filePath, content, "utf-8");
432
- }
433
-
434
408
  // ============================================================================
435
409
  // Rework Helpers
436
410
  // ============================================================================