| import { z } from "zod"; | ||
| import { get } from "../api-client.js"; | ||
| import { clean } from "./workspace.js"; | ||
| // ─── search_knowledge (MC-085) ─────────────────────────────────────────────── | ||
| // | ||
| // Thin digest over the web's unified `GET /api/search?q=` (tasks + wiki docs + | ||
| // project learnings, membership-scoped server-side). The point is discovery | ||
| // BEFORE building: surface what the team already knows so agents reuse instead | ||
| // of reinventing. | ||
| /** Max chars of a learning's content excerpt shown per result line. */ | ||
| const LEARNING_EXCERPT_CHARS = 120; | ||
| function projectSuffix(p) { | ||
| const label = clean(p?.name) || clean(p?.key); | ||
| return label ? ` (${label})` : ""; | ||
| } | ||
| function renderResults(query, res) { | ||
| const tasks = res.tasks ?? []; | ||
| const docs = res.docs ?? []; | ||
| const learnings = res.learnings ?? []; | ||
| if (tasks.length === 0 && docs.length === 0 && learnings.length === 0) { | ||
| return `No existing knowledge found for '${clean(query)}'.`; | ||
| } | ||
| const lines = []; | ||
| lines.push(`Existing knowledge matching "${clean(query)}":`); | ||
| if (tasks.length > 0) { | ||
| lines.push(""); | ||
| lines.push(`Tasks (${tasks.length}):`); | ||
| for (const t of tasks) { | ||
| const key = clean(t.ticketId) || t.id.slice(0, 8); | ||
| lines.push(`- ${key} [${clean(t.status) || "UNKNOWN"}] ${clean(t.title)}${projectSuffix(t.project)}`); | ||
| } | ||
| } | ||
| if (docs.length > 0) { | ||
| lines.push(""); | ||
| lines.push(`Docs (${docs.length}):`); | ||
| for (const d of docs) { | ||
| const scope = d.project ? projectSuffix(d.project) : d.projectId ? " (project wiki)" : " (team wiki)"; | ||
| lines.push(`- ${clean(d.title) || "Untitled"}${scope}`); | ||
| } | ||
| } | ||
| if (learnings.length > 0) { | ||
| lines.push(""); | ||
| lines.push(`Learnings (${learnings.length}):`); | ||
| for (const l of learnings) { | ||
| const title = clean(l.title); | ||
| const content = clean(l.content); | ||
| let excerpt = ""; | ||
| if (content && content !== title) { | ||
| excerpt = | ||
| content.length > LEARNING_EXCERPT_CHARS | ||
| ? `${content.slice(0, LEARNING_EXCERPT_CHARS)}…` | ||
| : content; | ||
| } | ||
| lines.push(`- [${clean(l.kind) || "learning"}] ${title || excerpt}${title && excerpt ? ` — ${excerpt}` : ""}`); | ||
| } | ||
| } | ||
| lines.push(""); | ||
| lines.push("Use get_task / get_doc for full detail before building anything these already cover."); | ||
| return lines.join("\n"); | ||
| } | ||
| export const searchTools = [ | ||
| { | ||
| name: "search_knowledge", | ||
| description: "Search the team's existing tasks, docs, and learnings across all your projects BEFORE building something new — reuse beats reinventing. Returns a compact digest of matching tasks (ticket, status, project), wiki docs, and recorded learnings, scoped to the teams you belong to. Call it whenever you're about to design, implement, or decide something that a teammate or agent may already have covered.", | ||
| inputSchema: z.object({ | ||
| query: z | ||
| .string() | ||
| .min(2) | ||
| .max(100) | ||
| .describe("Search terms (2-100 chars) — a feature name, ticket key, file, or concept"), | ||
| }), | ||
| handler: async (input) => { | ||
| const res = await get(`/api/search?q=${encodeURIComponent(input.query)}`); | ||
| return { | ||
| content: [{ type: "text", text: renderResults(input.query, res) }], | ||
| }; | ||
| }, | ||
| }, | ||
| ]; |
@@ -8,2 +8,2 @@ // Auto-generated from TaskPod/SKILL.md — regenerate on skill changes (MC-071). | ||
| /** The full skill body (markdown, no frontmatter). */ | ||
| export const BUNDLED_SKILL_BODY = "# Taskpod Agent Skill — the Central Mind Protocol\n\nYou are an AI agent (Claude Code, Codex, Cursor, or any MCP-capable tool) working in a codebase whose team runs on Taskpod (https://taskpod.in). Taskpod is the team's **central mind**: N developers and N agents work in parallel, and the board + its memory are the one place where everything they know converges. Your job is not just to write code — it is to **inherit the shared context before you start, mirror your work on the board while you work, and write back what you learned when you stop**, so the next agent or human starts smarter than you did.\n\nThis document is the working agreement. Every rule is imperative and testable. Follow it exactly.\n\n## The contract in one table\n\n| Phase | Obligation | Primary tool |\n|-------|-----------|--------------|\n| **Session start** | Pull the context digest and ingest it **before any work**; resume anything IN_PROGRESS | `sync_context` / `taskpod sync` · `resume_task` |\n| **During work** | Every status change is a checkpoint; progress is narrated; blockers become handoffs, never silence | `checkpoint_task` · `add_comment` · `handoff_to_human` |\n| **Session end / on discovery** | Record every non-obvious learning, decision, convention, or gotcha; then sync again so it propagates | `record_learning` · `sync_context` |\n\nA silent status change, an unrecorded gotcha, or an undocumented decision is a **bug in your behavior**, not a shortcut.\n\n---\n\n## Setup — connect your tool\n\n<!-- The commands and config snippets below are mirrored in lib/agent-snippets.ts\n (rendered by AgentConnectCard). Change one, change both. -->\n\nAll access uses one API key (Taskpod → **Settings → API Access**, keys look like `tp_live_...`). The MCP server ships in the `taskpod` npm package — no clone, no build. Self-hosting? Set `TASKPOD_API_URL` to your instance.\n\n### Claude Code\n\nOne command, run in the repo root:\n\n```bash\nnpx -y taskpod agent-setup\n```\n\nThis writes `.mcp.json` (registers the Taskpod MCP server) and appends a Taskpod protocol block to `CLAUDE.md` so every future session follows this skill automatically. Prefer manual control? Add this `.mcp.json` yourself:\n\n```json\n{\n \"mcpServers\": {\n \"taskpod\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"taskpod\", \"mcp\", \"--api-key\", \"tp_live_YOUR_KEY\"]\n }\n }\n}\n```\n\nIf you have run `taskpod login`, drop the `--api-key` pair — the server falls back to your stored token.\n\n`agent-setup` installs the curated quality skill pack automatically — alongside the Taskpod skill it drops the core pack (clean-code, design-patterns, pr-craft, verify-your-work, decompose-to-plan) into the repo's `.claude/skills/`. Pass `--no-skills` to skip it, or `--with-skills=all` to upgrade to the full pack (adds uxloom-journeys, java-annotations, and coverage-first-review).\n\n### Cursor\n\nCreate `.cursor/mcp.json` in the repo (or `~/.cursor/mcp.json` for all projects):\n\n```json\n{\n \"mcpServers\": {\n \"taskpod\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"taskpod\", \"mcp\", \"--api-key\", \"tp_live_YOUR_KEY\"]\n }\n }\n}\n```\n\nThen enable the server in Cursor Settings → MCP.\n\n### Codex\n\nAdd to `~/.codex/config.toml`:\n\n```toml\n[mcp_servers.taskpod]\ncommand = \"npx\"\nargs = [\"-y\", \"taskpod\", \"mcp\", \"--api-key\", \"tp_live_YOUR_KEY\"]\n```\n\n### Any other MCP client\n\nRegister a stdio server with the command:\n\n```bash\nnpx -y taskpod mcp --api-key tp_live_YOUR_KEY\n```\n\n### No MCP? Use REST\n\nEvery action below is also a plain REST call with the same key — full reference at https://taskpod.in/api-docs:\n\n```bash\ncurl -s https://taskpod.in/api/projects \\\n -H \"X-API-Key: tp_live_YOUR_KEY\" \\\n -H \"Content-Type: application/json\"\n```\n\n### Link the repo to its project\n\nIn a repo that isn't linked yet:\n\n```bash\nnpx -y taskpod init # repo → workspace: creates/links the Taskpod project\nnpx -y taskpod sync # pulls the context digest into .taskpod/\n```\n\n(Same thing from MCP: `init_workspace`, then `sync_context`.)\n\n---\n\n## 1. Session start (MANDATORY)\n\nDo these steps **in order, before reading or writing any code**:\n\n1. **Pull the digest.** Call `sync_context({ projectId })` — or run `taskpod sync` (or `taskpod pull`) in a linked repo. It returns a compact context digest: sprint state, the tasks you own, recent learnings, and the project's conventions.\n2. **Ingest it.** Read the digest end to end. Conventions and gotchas in it **constrain your work** — an agent that codes against a recorded convention is worse than one that never synced.\n3. **Resume, never restart.** If any task assigned to you is `IN_PROGRESS`, call `resume_task({ ticketId })` on it before anything else. It returns the last checkpoint, the last human comment, dependency state, and subtask progress.\n4. **Address humans first.** If `resume_task` reports `hasUnreadUserComments: true`, read and answer that feedback before doing anything else.\n5. **Then pick work.** Use `get_sprint_status({ projectId })` and its `nextRecommended` — the highest-priority unblocked task — not your memory of the project.\n\n> Starting work without `sync_context` is the protocol's cardinal sin: you will re-discover known gotchas, violate recorded conventions, and re-litigate settled decisions.\n\n## 2. During work\n\n### Every status change is a checkpoint\n\n**Never** change a task's status with a bare update. **Always** use `checkpoint_task` — it combines the status change with a mandatory comment saying *why* it moved and what happens next:\n\n```\ncheckpoint_task({\n taskId: \"<id>\",\n status: \"IN_PROGRESS\",\n aiStep: \"IMPLEMENT\",\n comment: \"Starting [AF-102]. Approach: extend lib/api-auth.ts with the refresh path; tests alongside. First step: stub the endpoint.\",\n aiAuthor: \"<your-model-name>\"\n})\n```\n\nWhat the checkpoint comment must contain, per transition:\n\n| Transition | The comment must include |\n|-----------|--------------------------|\n| → `IN_PROGRESS` | Approach, first step, dependencies verified |\n| → `IN_REVIEW` | Work report: AC status table, changes, how verified, PR link |\n| → `DONE` | Every acceptance criterion verified with evidence + changes summary |\n| → `CANCELLED` | Why, and any follow-up task created |\n| → `WAITING_APPROVAL` / `WAITING_INPUT` | The exact ask, and your default if unanswered |\n\nAlways set `aiStep` (`PLAN` → `RESEARCH` → `IMPLEMENT`) alongside status.\n\n### Narrate progress\n\nPost an `add_comment` roughly **every 30 minutes of active work**, or at any meaningful event — files changed, a decision made, a blocker hit, a test suite going green. The board must never go quiet while work is happening. Lead each comment with its type so histories stay scannable:\n\n| Type | Trigger | Must contain |\n|------|---------|--------------|\n| `checkpoint` | Any status change | New status · why · what's next |\n| `progress` | ~30 min / meaningful change | Done since last · in progress · next · remaining |\n| `decision` | A non-obvious choice | Context · options · decision · consequence |\n| `blocker` | Work can't proceed | What's blocked · why · what's needed · who can unblock |\n| `handoff` | Ownership changes party | From → to · state summary · the exact ask · links |\n| `work-report` | On `IN_REVIEW` / `DONE` | AC verification table · changes · how verified · PR |\n| `question` | Input needed, non-blocking | The question · why it matters · your default if no reply |\n\nFrom the CLI: `taskpod comment AF-102 -t progress \"...\"`.\n\n### Blocked? Hand off — never stall, never guess\n\nWhen you hit a decision, a missing secret, or a judgment call only a human can make:\n\n1. Call `handoff_to_human({ taskId, needs })` — it moves the task to `WAITING_INPUT` with the human as owner — or checkpoint to `WAITING_APPROVAL` when a plan needs sign-off.\n2. The comment states the **precise ask** and **your default if no reply** (so silence still has a defined outcome).\n3. Acknowledge every inbound handoff with a comment before you start on it.\n\nA work-report checkpoint, the shape reviewers expect on `IN_REVIEW`/`DONE`:\n\n```markdown\n**[IN_REVIEW]** AF-102 complete.\n\n| Acceptance criterion | Status | Evidence |\n| --- | --- | --- |\n| Silent refresh before expiry | ✅ | `refresh()` + test `refreshes-before-expiry` |\n| Failing refresh logs the user out | ✅ | test `logout-on-refresh-fail` |\n\n**Changes:** `lib/api-auth.ts`, `__tests__/auth.test.ts`.\n**How verified:** `npm test` green (3 new), manual expiry simulation.\n**PR:** #214 (CI green).\n```\n\n### Reference tickets everywhere\n\nWrite ticket keys as `[KEY-123]` in commit messages, PR titles/descriptions, and comments (e.g. `fix: token refresh race [AF-102]`). This is what lets the board, the repo, and the humans cross-reference your work.\n\n## 3. Session end & on discovery — write back to the central mind\n\nThis is what makes Taskpod more than a task tracker. Everything you learned that isn't already written down **dies with your context window unless you record it**.\n\n### Record learnings the moment you discover them\n\nWhenever you discover something non-obvious — and again in a sweep before you end the session — call:\n\n```\nrecord_learning({\n projectId: \"<id>\",\n kind: \"gotcha\", // learning | decision | convention | gotcha\n title: \"Tailwind v4 classes unreliable under Turbopack\",\n content: \"Layout-critical CSS must use inline style props; Tailwind utility classes intermittently drop under Turbopack dev builds. Bit AF-088 and AF-094.\"\n})\n```\n\n| Kind | Record when you… | Example title |\n|------|------------------|---------------|\n| `learning` | Discovered something non-obvious about the system or domain | \"Webhook retries are at-least-once — handlers must be idempotent\" |\n| `decision` | Made a choice with real alternatives | \"Chose file-based token storage over OS keychain\" |\n| `convention` | Found (or set) a pattern all future work must repeat | \"Every API route uses the dual-auth pattern from lib/api-auth.ts\" |\n| `gotcha` | Lost time to a trap the next agent would also hit | \"prisma db push required after schema change or dev server 500s\" |\n\n**Rules for a good learning:**\n\n- **One insight per entry.** Never batch three discoveries into one record.\n- **Titled and concise.** A short imperative title; content is the what + why-it-matters in a few lines. Not an essay, not a diff.\n- **Novel only.** Never record what the repo (README, CLAUDE.md, code comments) or the board (task descriptions, existing learnings) already says. Check the digest's recent learnings first — duplicates poison the digest.\n- **Actionable for a stranger.** Write for the next agent with zero context: name files, commands, and error messages.\n\n### Then sync again\n\nEnd every session with:\n\n1. **Board truth check** — every task you touched is in its true status with a checkpoint; anything mid-flight has a fresh `progress` comment. Never leave a task `IN_PROGRESS` and silent.\n2. **Learning sweep** — anything non-obvious from this session recorded via `record_learning` (one entry each).\n3. **`sync_context` again** (or `taskpod sync`, which pushes learnings up and pulls the fresh digest down). This confirms your write-back landed and hands the next agent — or the same developer's other agent, already running — the updated digest.\n\n> This loop is the point: N developers × N agents, one memory. What one agent learns at 10:04, another inherits at 10:05.\n\n---\n\n## Status lifecycle\n\n```\nBACKLOG → TODO → IN_PROGRESS → IN_REVIEW → DONE\n │ │\n └── CANCELLED ─┘\n```\n\n| Status | Meaning |\n|--------|---------|\n| `BACKLOG` | Created, not yet planned (AI-staged plans wait here) |\n| `TODO` | Planned, dependencies met, ready to start |\n| `IN_PROGRESS` | Actively being worked — must never go comment-silent |\n| `IN_REVIEW` | Delivered, awaiting human review (agents finish here, with a work report) |\n| `DONE` | All acceptance + exit criteria verified in the checkpoint |\n| `CANCELLED` | Descoped — the checkpoint says why |\n| `WAITING_APPROVAL` | Parked on a human decision (plans, agent asks) |\n| `WAITING_INPUT` | Handed back to a human; the ask + your default are in the comment |\n| `GRADING` | Agent-plane verification of finished work (set by the orchestrator, not by hand) |\n\nWhen completing a task unblocks others, checkpoint each newly unblocked task to `TODO` with a comment naming what unblocked it.\n\n## Creating new work\n\nEvery task you create gets a full description — no title-only tasks, ever:\n\n```markdown\n## Problem Statement\n[What needs to be built and why]\n\n## Proposed Solution\n[Specific implementation approach]\n\n## Acceptance Criteria\n- [ ] [Specific, testable criterion]\n- [ ] [Specific, testable criterion]\n\n## Exit Criteria\n- [ ] Code compiles with zero errors\n- [ ] Tests written and passing\n```\n\nThen: set a priority (`URGENT`/`HIGH`/`MEDIUM`/`LOW`), wire ordering with `add_dependency` (schema blocks API blocks UI…), and checkpoint the new task to `TODO` with a creation comment. A task without acceptance criteria cannot be handed to an agent — the checklist is what makes work specifiable.\n\n---\n\n## Tool & command reference\n\nThe MCP server registers 50+ tools. These are the ones the protocol turns on:\n\n### Central-mind tools (the protocol core)\n\n| Tool | When |\n|------|------|\n| `sync_context` | **Session start and end** — returns the compact context digest (sprint, owned tasks, recent learnings, conventions) |\n| `record_learning` | **On discovery / session end** — `{ projectId, kind: learning\\|decision\\|convention\\|gotcha, title, content }` |\n| `init_workspace` | Once per repo — link it to its Taskpod project |\n| `checkpoint_task` | **Every status change** — status + mandatory why-comment, atomically |\n| `resume_task` | **Before touching any existing task** — last checkpoint, unread human comments, dependency + subtask state |\n| `get_sprint_status` | Board overview + `nextRecommended` task |\n| `handoff_to_human` | Stuck → `WAITING_INPUT` with a precise ask; use instead of stalling or guessing |\n\n### CRUD tools (the other 40+)\n\n| Area | Tools |\n|------|-------|\n| Teams & members | `get_teams`, `create_team`, `update_team`, `delete_team`, `add_team_member`, `remove_team_member`, `list_team_members`, `list_users` |\n| Projects | `create_project`, `list_projects`, `get_project_structure`, `update_project`, `delete_project`, `export_project`, `add_project_member`, `remove_project_member`, `list_project_members` |\n| Folders | `create_folder`, `list_folders`, `update_folder`, `delete_folder` |\n| Tasks | `create_task`, `get_task`, `update_task`, `delete_task`, `list_tasks`, `search_tasks`, `create_subtask`, `log_time` |\n| Collaboration | `add_comment`, `get_recent_activity`, `add_dependency`, `remove_dependency`, `add_task_watcher`, `remove_task_watcher`, `list_task_watchers` |\n| Resources | `list_project_resources`, `add_project_resource`, `remove_project_resource` |\n\n### CLI\n\n| Command | Does |\n|---------|------|\n| `taskpod init` | Repo → workspace: create/link the project from the terminal |\n| `taskpod sync` | ↓ pull the context digest into `.taskpod/` · ↑ push recorded learnings |\n| `taskpod agent-setup` | Write `.mcp.json` + a `CLAUDE.md` protocol block into the repo |\n| `taskpod status` | Sprint status for the linked project |\n| `taskpod mine` | Your tasks — status, ETA, blockers |\n| `taskpod show AF-102` | Full task detail with comments |\n| `taskpod start AF-102` | Checkpoint to `IN_PROGRESS` |\n| `taskpod done AF-102` | Checkpoint to `DONE` (prompts for the work report) |\n| `taskpod comment AF-102 -t <type>` | Typed comment (see the taxonomy above) |\n| `taskpod handoff AF-102` | Hand ownership to a human or agent |\n| `taskpod pull` | Refresh the `.taskpod/` context bundle only |\n| `taskpod login` | Store your token (then `--api-key` is optional everywhere) |\n| `taskpod mcp` | Run the MCP server on stdio |\n\nIn a linked repo, read `.taskpod/` as normal repo context: `context.md` (project overview), `board.json` (every task), `mine.md` (your tasks), `deps.md` (what blocks what), `resources.md` (repos, docs, consoles), `SKILL.md` (this protocol).\n\n---\n\n## Never do\n\n- **Never** change a task's status without a checkpoint comment.\n- **Never** start work without `sync_context` — or on an existing task, without `resume_task`.\n- **Never** ignore unread user comments; address them before new work.\n- **Never** mark `DONE` without verifying every acceptance criterion, with evidence, in the checkpoint.\n- **Never** record a learning the repo or board already documents — check the digest first.\n- **Never** batch multiple insights into one `record_learning` entry.\n- **Never** leave a task `IN_PROGRESS` and silent at session end — checkpoint it or post a `progress` comment.\n- **Never** guess through a blocker — `handoff_to_human` with a precise ask and your default.\n- **Never** create a task without a description, acceptance criteria, and a priority.\n- **Never** end a session without the learning sweep + final `sync_context`.\n\n## Loading this skill\n\nGive your AI tool this prompt (works with MCP configured, or over plain REST with https://taskpod.in/api-docs):\n\n```\nRead https://taskpod.in/skill and follow it for all work. Taskpod is the\nteam's central mind. Non-negotiable: call sync_context at session start and\ningest the digest before any work; resume_task before touching any existing\ntask; checkpoint_task for EVERY status change; record_learning for every\nnon-obvious decision, convention, or gotcha you discover (one per entry,\nnever duplicating what's already recorded); and sync_context again before\nyou stop. API key: <your tp_live_... token>.\n```\n"; | ||
| export const BUNDLED_SKILL_BODY = "# Taskpod Agent Skill — the Central Mind Protocol\n\nYou are an AI agent (Claude Code, Codex, Cursor, or any MCP-capable tool) working in a codebase whose team runs on Taskpod (https://taskpod.in). Taskpod is the team's **central mind**: N developers and N agents work in parallel, and the board + its memory are the one place where everything they know converges. Your job is not just to write code — it is to **inherit the shared context before you start, mirror your work on the board while you work, and write back what you learned when you stop**, so the next agent or human starts smarter than you did.\n\nThis document is the working agreement. Every rule is imperative and testable. Follow it exactly.\n\n## The contract in one table\n\n| Phase | Obligation | Primary tool |\n|-------|-----------|--------------|\n| **Session start** | Pull the context digest and ingest it **before any work**; resume anything IN_PROGRESS; reuse-check before you build | `sync_context` / `taskpod sync` · `resume_task` · `search_knowledge` |\n| **During work** | Every status change is a checkpoint; progress is narrated; approach choices land in the living design doc; blockers become handoffs, never silence | `checkpoint_task` · `add_comment` · `update_doc` · `handoff_to_human` |\n| **Session end / on discovery** | Record every non-obvious learning, decision, convention, or gotcha; then sync again so it propagates | `record_learning` · `sync_context` |\n\nA silent status change, an unrecorded gotcha, or an undocumented decision is a **bug in your behavior**, not a shortcut.\n\n---\n\n## Setup — connect your tool\n\n<!-- The commands and config snippets below are mirrored in lib/agent-snippets.ts\n (rendered by AgentConnectCard). Change one, change both. -->\n\nAll access uses one API key (Taskpod → **Settings → API Access**, keys look like `tp_live_...`). The MCP server ships in the `taskpod` npm package — no clone, no build. Self-hosting? Set `TASKPOD_API_URL` to your instance.\n\n### Claude Code\n\nOne command, run in the repo root:\n\n```bash\nnpx -y taskpod agent-setup\n```\n\nThis writes `.mcp.json` (registers the Taskpod MCP server) and appends a Taskpod protocol block to `CLAUDE.md` so every future session follows this skill automatically. Prefer manual control? Add this `.mcp.json` yourself:\n\n```json\n{\n \"mcpServers\": {\n \"taskpod\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"taskpod\", \"mcp\", \"--api-key\", \"tp_live_YOUR_KEY\"]\n }\n }\n}\n```\n\nIf you have run `taskpod login`, drop the `--api-key` pair — the server falls back to your stored token.\n\n`agent-setup` installs the curated quality skill pack automatically — alongside the Taskpod skill it drops the core pack (clean-code, design-patterns, pr-craft, verify-your-work, decompose-to-plan) into the repo's `.claude/skills/`. Pass `--no-skills` to skip it, or `--with-skills=all` to upgrade to the full pack (adds uxloom-journeys, java-annotations, and coverage-first-review).\n\n### Cursor\n\nCreate `.cursor/mcp.json` in the repo (or `~/.cursor/mcp.json` for all projects):\n\n```json\n{\n \"mcpServers\": {\n \"taskpod\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"taskpod\", \"mcp\", \"--api-key\", \"tp_live_YOUR_KEY\"]\n }\n }\n}\n```\n\nThen enable the server in Cursor Settings → MCP.\n\n### Codex\n\nAdd to `~/.codex/config.toml`:\n\n```toml\n[mcp_servers.taskpod]\ncommand = \"npx\"\nargs = [\"-y\", \"taskpod\", \"mcp\", \"--api-key\", \"tp_live_YOUR_KEY\"]\n```\n\n### Any other MCP client\n\nRegister a stdio server with the command:\n\n```bash\nnpx -y taskpod mcp --api-key tp_live_YOUR_KEY\n```\n\n### No MCP? Use REST\n\nEvery action below is also a plain REST call with the same key — full reference at https://taskpod.in/api-docs:\n\n```bash\ncurl -s https://taskpod.in/api/projects \\\n -H \"X-API-Key: tp_live_YOUR_KEY\" \\\n -H \"Content-Type: application/json\"\n```\n\n### Link the repo to its project\n\nIn a repo that isn't linked yet:\n\n```bash\nnpx -y taskpod init # repo → workspace: creates/links the Taskpod project\nnpx -y taskpod sync # pulls the context digest into .taskpod/\n```\n\nWhen `init` creates a brand-new project, it offers to pre-load the board from the repo (`taskpod ingest`): README + `docs/**/*.md` become wiki pages, detected conventions become learnings, and `TODO:`/`FIXME:` comments become backlog tasks. Idempotent — re-running never duplicates.\n\n(Same thing from MCP: `init_workspace`, then `sync_context`.)\n\n---\n\n## 1. Session start (MANDATORY)\n\nDo these steps **in order, before reading or writing any code**:\n\n1. **Pull the digest.** Call `sync_context({ projectId })` — or run `taskpod sync` (or `taskpod pull`) in a linked repo. It returns a compact context digest: sprint state, the tasks you own, recent learnings, and the project's conventions.\n2. **Ingest it.** Read the digest end to end. Conventions and gotchas in it **constrain your work** — an agent that codes against a recorded convention is worse than one that never synced.\n3. **Resume, never restart.** If any task assigned to you is `IN_PROGRESS`, call `resume_task({ ticketId })` on it before anything else. It returns the last checkpoint, the last human comment, dependency state, and subtask progress.\n4. **Address humans first.** If `resume_task` reports `hasUnreadUserComments: true`, read and answer that feedback before doing anything else.\n5. **Then pick work.** Use `get_sprint_status({ projectId })` and its `nextRecommended` — the highest-priority unblocked task — not your memory of the project.\n6. **Reuse-check before you build.** Before implementing anything non-trivial, call `search_knowledge({ query })` — it searches tasks, docs, and learnings across **every project you can see**. If the team already built, decided, or learned it, you surface that instead of rebuilding it (rules below).\n\n> Starting work without `sync_context` is the protocol's cardinal sin: you will re-discover known gotchas, violate recorded conventions, and re-litigate settled decisions.\n\n## 2. During work\n\n### Reuse before you build\n\nYour team is N developers × N agents — odds are someone already solved part of your problem. Before implementing anything non-trivial (a component, an integration, an algorithm, a policy), call:\n\n```\nsearch_knowledge({ query: \"rate limiting middleware\" })\n```\n\nIt returns matching tasks, docs, and learnings across **every project you can see** — this one and its siblings. On a hit, **surface it to the human instead of re-implementing**: *\"Your team already has X in project Y — reuse it?\"* Then follow their call.\n\nTwo rules keep this cheap:\n\n- **One search per distinct concept.** Search once per idea, not once per keyword variation.\n- **Never search what the digest already answers.** The `sync_context` digest is pre-pulled context; query only what it doesn't cover.\n\n### Every status change is a checkpoint\n\n**Never** change a task's status with a bare update. **Always** use `checkpoint_task` — it combines the status change with a mandatory comment saying *why* it moved and what happens next:\n\n```\ncheckpoint_task({\n taskId: \"<id>\",\n status: \"IN_PROGRESS\",\n aiStep: \"IMPLEMENT\",\n comment: \"Starting [AF-102]. Approach: extend lib/api-auth.ts with the refresh path; tests alongside. First step: stub the endpoint.\",\n aiAuthor: \"<your-model-name>\"\n})\n```\n\nWhat the checkpoint comment must contain, per transition:\n\n| Transition | The comment must include |\n|-----------|--------------------------|\n| → `IN_PROGRESS` | Approach, first step, dependencies verified |\n| → `IN_REVIEW` | Work report: AC status table, changes, how verified, PR link |\n| → `DONE` | Every acceptance criterion verified with evidence + changes summary |\n| → `CANCELLED` | Why, and any follow-up task created |\n| → `WAITING_APPROVAL` / `WAITING_INPUT` | The exact ask, and your default if unanswered |\n\nAlways set `aiStep` (`PLAN` → `RESEARCH` → `IMPLEMENT`) alongside status.\n\n### Narrate progress\n\nPost an `add_comment` roughly **every 30 minutes of active work**, or at any meaningful event — files changed, a decision made, a blocker hit, a test suite going green. The board must never go quiet while work is happening. Lead each comment with its type so histories stay scannable:\n\n| Type | Trigger | Must contain |\n|------|---------|--------------|\n| `checkpoint` | Any status change | New status · why · what's next |\n| `progress` | ~30 min / meaningful change | Done since last · in progress · next · remaining |\n| `decision` | A non-obvious choice | Context · options · decision · consequence |\n| `blocker` | Work can't proceed | What's blocked · why · what's needed · who can unblock |\n| `handoff` | Ownership changes party | From → to · state summary · the exact ask · links |\n| `work-report` | On `IN_REVIEW` / `DONE` | AC verification table · changes · how verified · PR |\n| `question` | Input needed, non-blocking | The question · why it matters · your default if no reply |\n\nFrom the CLI: `taskpod comment AF-102 -t progress \"...\"`.\n\n### Maintain the living design doc\n\nA `decision` comment records a choice on the task; the project's **design doc** is where the next agent finds it without knowing which task to read. Whenever work involves a non-trivial approach choice, maintain it:\n\n1. **`list_docs` first.** If the design doc exists, `update_doc` it — only `create_doc` when the project genuinely has none. One design doc per project; duplicates fragment the record.\n2. **Each entry records three things**, with ticket keys linked: the **chosen approach** (a line or two), the **alternatives considered** (named, not elaborated), and the **why** — the deciding constraint or tradeoff. E.g. *\"[AF-120] Board realtime: chose Postgres LISTEN/NOTIFY over polling — sub-second updates without connection churn. Also considered: SSE fan-out service (extra infra).\"*\n3. **When the approach changes, update the same entry in the same doc.** A stale decision record is worse than none.\n\nKeep entries short — the doc is a decision record, not an essay.\n\n### Blocked? Hand off — never stall, never guess\n\nWhen you hit a decision, a missing secret, or a judgment call only a human can make:\n\n1. Call `handoff_to_human({ taskId, needs })` — it moves the task to `WAITING_INPUT` with the human as owner — or checkpoint to `WAITING_APPROVAL` when a plan needs sign-off.\n2. The comment states the **precise ask** and **your default if no reply** (so silence still has a defined outcome).\n3. Acknowledge every inbound handoff with a comment before you start on it.\n\nA work-report checkpoint, the shape reviewers expect on `IN_REVIEW`/`DONE`:\n\n```markdown\n**[IN_REVIEW]** AF-102 complete.\n\n| Acceptance criterion | Status | Evidence |\n| --- | --- | --- |\n| Silent refresh before expiry | ✅ | `refresh()` + test `refreshes-before-expiry` |\n| Failing refresh logs the user out | ✅ | test `logout-on-refresh-fail` |\n\n**Changes:** `lib/api-auth.ts`, `__tests__/auth.test.ts`.\n**How verified:** `npm test` green (3 new), manual expiry simulation.\n**PR:** #214 (CI green).\n```\n\n### Reference tickets everywhere\n\nWrite ticket keys as `[KEY-123]` in commit messages, PR titles/descriptions, and comments (e.g. `fix: token refresh race [AF-102]`). This is what lets the board, the repo, and the humans cross-reference your work.\n\n## 3. Session end & on discovery — write back to the central mind\n\nThis is what makes Taskpod more than a task tracker. Everything you learned that isn't already written down **dies with your context window unless you record it**.\n\n### Record learnings the moment you discover them\n\nWhenever you discover something non-obvious — and again in a sweep before you end the session — call:\n\n```\nrecord_learning({\n projectId: \"<id>\",\n kind: \"gotcha\", // learning | decision | convention | gotcha\n title: \"Tailwind v4 classes unreliable under Turbopack\",\n content: \"Layout-critical CSS must use inline style props; Tailwind utility classes intermittently drop under Turbopack dev builds. Bit AF-088 and AF-094.\"\n})\n```\n\n| Kind | Record when you… | Example title |\n|------|------------------|---------------|\n| `learning` | Discovered something non-obvious about the system or domain | \"Webhook retries are at-least-once — handlers must be idempotent\" |\n| `decision` | Made a choice with real alternatives | \"Chose file-based token storage over OS keychain\" |\n| `convention` | Found (or set) a pattern all future work must repeat | \"Every API route uses the dual-auth pattern from lib/api-auth.ts\" |\n| `gotcha` | Lost time to a trap the next agent would also hit | \"prisma db push required after schema change or dev server 500s\" |\n\n**Rules for a good learning:**\n\n- **One insight per entry.** Never batch three discoveries into one record.\n- **Titled and concise.** A short imperative title; content is the what + why-it-matters in a few lines. Not an essay, not a diff.\n- **Novel only.** Never record what the repo (README, CLAUDE.md, code comments) or the board (task descriptions, existing learnings) already says. Check the digest's recent learnings first — duplicates poison the digest.\n- **Actionable for a stranger.** Write for the next agent with zero context: name files, commands, and error messages.\n\n### Then sync again\n\nEnd every session with:\n\n1. **Board truth check** — every task you touched is in its true status with a checkpoint; anything mid-flight has a fresh `progress` comment. Never leave a task `IN_PROGRESS` and silent.\n2. **Learning sweep** — anything non-obvious from this session recorded via `record_learning` (one entry each).\n3. **`sync_context` again** (or `taskpod sync`, which pushes learnings up and pulls the fresh digest down). This confirms your write-back landed and hands the next agent — or the same developer's other agent, already running — the updated digest.\n\n> This loop is the point: N developers × N agents, one memory. What one agent learns at 10:04, another inherits at 10:05.\n\n---\n\n## Status lifecycle\n\n```\nBACKLOG → TODO → IN_PROGRESS → IN_REVIEW → DONE\n │ │\n └── CANCELLED ─┘\n```\n\n| Status | Meaning |\n|--------|---------|\n| `BACKLOG` | Created, not yet planned (AI-staged plans wait here) |\n| `TODO` | Planned, dependencies met, ready to start |\n| `IN_PROGRESS` | Actively being worked — must never go comment-silent |\n| `IN_REVIEW` | Delivered, awaiting human review (agents finish here, with a work report) |\n| `DONE` | All acceptance + exit criteria verified in the checkpoint |\n| `CANCELLED` | Descoped — the checkpoint says why |\n| `WAITING_APPROVAL` | Parked on a human decision (plans, agent asks) |\n| `WAITING_INPUT` | Handed back to a human; the ask + your default are in the comment |\n| `GRADING` | Agent-plane verification of finished work (set by the orchestrator, not by hand) |\n\nWhen completing a task unblocks others, checkpoint each newly unblocked task to `TODO` with a comment naming what unblocked it.\n\n## Creating new work\n\nEvery task you create gets a full description — no title-only tasks, ever:\n\n```markdown\n## Problem Statement\n[What needs to be built and why]\n\n## Proposed Solution\n[Specific implementation approach]\n\n## Acceptance Criteria\n- [ ] [Specific, testable criterion]\n- [ ] [Specific, testable criterion]\n\n## Exit Criteria\n- [ ] Code compiles with zero errors\n- [ ] Tests written and passing\n```\n\nThen: set a priority (`URGENT`/`HIGH`/`MEDIUM`/`LOW`), wire ordering with `add_dependency` (schema blocks API blocks UI…), and checkpoint the new task to `TODO` with a creation comment. A task without acceptance criteria cannot be handed to an agent — the checklist is what makes work specifiable.\n\n### Handed a broad goal? Decompose, recommend, wait\n\nWhen the human gives a broad or ambiguous goal (\"add billing\", \"make onboarding better\"), **never charge ahead on a guess**. Run this playbook:\n\n1. **Decompose** the goal into concrete sub-problems (per the decompose-to-plan skill, if installed).\n2. **For each hard sub-problem**, present 2–3 viable approaches with a one-line tradeoff each.\n3. **Recommend exactly one** and say why — the human wants a position, not a menu.\n4. **Stage the plan on the board**: create the sub-tasks as `BACKLOG` with dependencies wired, then checkpoint the parent to `WAITING_APPROVAL` — the human decides before any implementation starts.\n\n---\n\n## Tool & command reference\n\nThe MCP server registers 68 tools. These are the ones the protocol turns on:\n\n### Central-mind tools (the protocol core)\n\n| Tool | When |\n|------|------|\n| `sync_context` | **Session start and end** — returns the compact context digest (sprint, owned tasks, recent learnings, conventions) |\n| `record_learning` | **On discovery / session end** — `{ projectId, kind: learning\\|decision\\|convention\\|gotcha, title, content }` |\n| `search_knowledge` | **Before building anything non-trivial** — `{ query }` → matching tasks, docs, and learnings across every project you can see; reuse beats rebuild |\n| `init_workspace` | Once per repo — link it to its Taskpod project |\n| `checkpoint_task` | **Every status change** — status + mandatory why-comment, atomically |\n| `resume_task` | **Before touching any existing task** — last checkpoint, unread human comments, dependency + subtask state |\n| `get_sprint_status` | Board overview + `nextRecommended` task |\n| `handoff_to_human` | Stuck → `WAITING_INPUT` with a precise ask; use instead of stalling or guessing |\n\n### CRUD tools (the other 60)\n\n| Area | Tools |\n|------|-------|\n| Teams & members | `get_teams`, `create_team`, `update_team`, `delete_team`, `add_team_member`, `remove_team_member`, `list_team_members`, `list_users` |\n| Projects | `create_project`, `list_projects`, `get_project_structure`, `update_project`, `delete_project`, `export_project`, `add_project_member`, `remove_project_member`, `list_project_members` |\n| Folders | `create_folder`, `list_folders`, `update_folder`, `delete_folder` |\n| Tasks | `create_task`, `get_task`, `update_task`, `delete_task`, `list_tasks`, `search_tasks`, `create_subtask`, `log_time` |\n| Collaboration | `add_comment`, `get_recent_activity`, `add_dependency`, `remove_dependency`, `add_task_watcher`, `remove_task_watcher`, `list_task_watchers` |\n| Resources | `list_project_resources`, `add_project_resource`, `remove_project_resource` |\n| Sprints | `create_sprint`, `list_sprints`, `update_sprint`, `close_sprint`, `delete_sprint` |\n| Custom fields | `create_custom_field`, `list_custom_fields`, `set_task_fields` |\n| Workflow | `create_workflow_column`, `list_workflow_columns` |\n| Docs | `create_doc`, `list_docs`, `get_doc`, `update_doc` |\n| Initiatives | `create_initiative`, `list_initiatives` |\n| Approvals | `list_approvals`, `decide_approval` |\n| OKRs | `list_objectives`, `update_key_result` |\n| Metrics | `get_project_metrics` |\n\n### CLI\n\n| Command | Does |\n|---------|------|\n| `taskpod init` | Repo → workspace: create/link the project from the terminal. When it creates a fresh project it offers to run `ingest` (`--no-ingest` to skip) |\n| `taskpod sync` | ↓ pull the context digest into `.taskpod/` · ↑ push recorded learnings |\n| `taskpod ingest` | Bootstrap the board from an existing repo: README/docs → wiki, conventions → memory, TODOs → backlog; idempotent (`--dry-run` previews) |\n| `taskpod agent-setup` | Write `.mcp.json` + a `CLAUDE.md` protocol block into the repo, and install the TaskPod skill pack into `.claude/skills/` |\n| `taskpod status` | Sprint status for the linked project |\n| `taskpod mine` | Your tasks — status, ETA, blockers |\n| `taskpod show AF-102` | Full task detail with comments |\n| `taskpod start AF-102` | Checkpoint to `IN_PROGRESS` |\n| `taskpod done AF-102` | Checkpoint to `IN_REVIEW` (with work report) |\n| `taskpod comment AF-102 -t <type>` | Typed comment (see the taxonomy above) |\n| `taskpod handoff AF-102` | Hand ownership to a human or agent |\n| `taskpod pull` | Refresh the `.taskpod/` context bundle only |\n| `taskpod login` | Store your token (then `--api-key` is optional everywhere) |\n| `taskpod mcp` | Run the MCP server on stdio |\n\nIn a linked repo, read `.taskpod/` as normal repo context: `context.md` (project overview), `board.json` (every task), `mine.md` (your tasks), `deps.md` (what blocks what), `resources.md` (repos, docs, consoles), `LEARNINGS.md` (the recorded learnings), `AGENTS.md` (the agent working agreement), `SKILL.md` (this protocol).\n\n---\n\n## The anti-friction tenets\n\nThe board serves the human — it never interrupts them. Every rule above bends to these:\n\n- **Batch board updates at natural pauses** — a finished step, a green test run, a checkpoint — not interleaved through the human's flow.\n- **If nothing new happened, write nothing.** An update without new information is noise, and noise teaches humans to stop reading.\n- **A declined suggestion stays declined.** Reuse hit, plan tweak, doc idea — offer once, then drop it unless the facts change.\n- **Never block the human's flow on board ops.** Board writes ride alongside the work; the human never waits on them.\n- **Helpfulness is the human keeping the connection** — measured by whether they come back tomorrow, not by your activity volume today.\n\n## Never do\n\n- **Never** change a task's status without a checkpoint comment.\n- **Never** start work without `sync_context` — or on an existing task, without `resume_task`.\n- **Never** ignore unread user comments; address them before new work.\n- **Never** mark `DONE` without verifying every acceptance criterion, with evidence, in the checkpoint.\n- **Never** record a learning the repo or board already documents — check the digest first.\n- **Never** batch multiple insights into one `record_learning` entry.\n- **Never** leave a task `IN_PROGRESS` and silent at session end — checkpoint it or post a `progress` comment.\n- **Never** spam comments — an update that adds no new information is noise, not narration.\n- **Never** re-suggest reuse (or anything else) the human already declined.\n- **Never** create a second design doc — `list_docs`, then update the existing one.\n- **Never** repeat a `search_knowledge` query the digest already answers — one search per distinct concept.\n- **Never** guess through a blocker — `handoff_to_human` with a precise ask and your default.\n- **Never** create a task without a description, acceptance criteria, and a priority.\n- **Never** end a session without the learning sweep + final `sync_context`.\n\n## Loading this skill\n\nGive your AI tool this prompt (works with MCP configured, or over plain REST with https://taskpod.in/api-docs):\n\n```\nRead https://taskpod.in/skill and follow it for all work. Taskpod is the\nteam's central mind. Non-negotiable: call sync_context at session start and\ningest the digest before any work; resume_task before touching any existing\ntask; search_knowledge before building anything non-trivial (reuse beats\nrebuild); checkpoint_task for EVERY status change; record_learning for every\nnon-obvious decision, convention, or gotcha you discover (one per entry,\nnever duplicating what's already recorded); and sync_context again before\nyou stop. API key: <your tp_live_... token>.\n```\n"; |
+3
-1
@@ -24,6 +24,7 @@ /** | ||
| import { workspaceTools } from "./tools/workspace.js"; | ||
| import { searchTools } from "./tools/search.js"; | ||
| import { approvalTools } from "./tools/approvals.js"; | ||
| import { okrTools } from "./tools/okrs.js"; | ||
| export const SERVER_NAME = "taskpod"; | ||
| export const SERVER_VERSION = "0.4.6"; | ||
| export const SERVER_VERSION = "0.4.7"; | ||
| export const allTools = [ | ||
@@ -45,2 +46,3 @@ ...teamTools, | ||
| ...workspaceTools, | ||
| ...searchTools, | ||
| ...approvalTools, | ||
@@ -47,0 +49,0 @@ ...okrTools, |
@@ -26,3 +26,3 @@ import { z } from "zod"; | ||
| */ | ||
| function clean(s) { | ||
| export function clean(s) { | ||
| if (!s) | ||
@@ -29,0 +29,0 @@ return ""; |
+1
-1
| { | ||
| "name": "taskpod", | ||
| "version": "0.4.6", | ||
| "version": "0.4.7", | ||
| "description": "The Taskpod developer CLI and MCP server — sync project context to your machine and AI, and manage teams, projects, and tasks from any MCP client.", | ||
@@ -5,0 +5,0 @@ "type": "module", |
+4
-2
@@ -61,3 +61,3 @@ # taskpod | ||
| | `verify-your-work` | Before claiming done — drive the affected flow end-to-end, verify acceptance criteria one by one, report failures and skipped steps faithfully | | ||
| | `decompose-to-plan` | Decompose briefs into 3–6 epics × 2–6 tasks with explicit acceptance criteria, backward-only dependencies, and honest priorities | | ||
| | `decompose-to-plan` | Decompose briefs into 3–6 epics × 2–6 tasks with explicit acceptance criteria, backward-only dependencies, and honest priorities — hard sub-problems get 2–3 candidate approaches with tradeoffs and a recommendation, staged `WAITING_APPROVAL` for the human call | | ||
| | `uxloom-journeys` *(all)* | Journey-first UI/UX validation — model journeys as state machines in a JourneyGraph, then run the bundled deterministic validator (`validate.mjs`, no network) to 0 errors | | ||
@@ -176,3 +176,3 @@ | `java-annotations` *(all)* | Choose official Java annotations with judgment — Lombok vs records, Micrometer/Powertools instrumentation, Jakarta Validation vs JSpecify, Dagger vs Guice vs Spring | | ||
| The three tools an agent needs to bootstrap and stay grounded in a repo: | ||
| The four tools an agent needs to bootstrap and stay grounded in a repo: | ||
@@ -182,2 +182,3 @@ - `init_workspace({ repoUrl? | repoFullName?, teamId?, name? })` — create (or find) the Taskpod project for a git repository. The repo is the project's identity: calling it twice for the same repo returns the same project (`created: false`). | ||
| - `record_learning({ projectId, kind?, title, content })` — write a learning | decision | convention | gotcha to the project's shared memory, so every human (`taskpod sync`) and agent (`sync_context`) sees it on their next pull. | ||
| - `search_knowledge({ query })` — search the team's existing tasks, wiki docs, and learnings across all your projects, returned as a compact digest (tickets with status + project, doc titles, learning excerpts). **Reuse before build**: call it before designing or implementing anything new — someone (human or agent) may already have solved it, decided it, or written down why not to. | ||
@@ -232,2 +233,3 @@ There is deliberately no `ingest_workspace` MCP tool: the hosted MCP server has no access to your repo's files, so it can't scan them for you. `taskpod ingest` is the CLI's repo-side scanner; an agent working inside the repo achieves the same result with its own file access plus `create_doc`, `record_learning`, and `create_task` (the decompose-to-plan path). | ||
| | My tasks | `taskpod mine` | `list_tasks` (filtered) | | ||
| | Search existing knowledge | Taskpod web (top-nav search) | `search_knowledge` | | ||
| | Task detail | `taskpod show <ticket>` | `get_task` / `resume_task` | | ||
@@ -234,0 +236,0 @@ | Start work | `taskpod start <ticket>` | `checkpoint_task` (→ IN_PROGRESS) | |
@@ -72,2 +72,28 @@ --- | ||
| ## Hard sub-problems: propose approaches, don't pick silently | ||
| When a sub-problem has more than one credible design (storage engine, auth | ||
| flow, sync strategy, build-vs-buy...), the plan must surface the choice — | ||
| a plan that silently commits to one architecture steals a decision that | ||
| belongs to the humans paying for it. | ||
| For each hard sub-problem: | ||
| - **Lay out 2–3 genuinely different approaches** — not one real option and | ||
| two strawmen. If you can only think of one credible approach, it isn't a | ||
| hard sub-problem; just build it. | ||
| - **One line of tradeoffs each** — the cost that would make someone pick | ||
| the other one ("simplest, but polls every 5s", "real-time, but needs a | ||
| sticky WebSocket tier"). No essays. | ||
| - **Recommend exactly one, and say why** — the recommendation is yours to | ||
| make; the decision is not. "It depends" is not a recommendation. | ||
| - **Stage it for the human**: create the plan's tasks as `BACKLOG` and put | ||
| the decision itself in a task checkpointed to `WAITING_APPROVAL` whose | ||
| comment carries the approaches, tradeoffs, and your recommendation + | ||
| default. Work starts when a human approves — never before. | ||
| Search first: before proposing any approach, check the board's existing | ||
| knowledge (`search_knowledge` / the sync digest) — a prior decision or | ||
| gotcha may have already settled the choice. | ||
| ## Self-check before presenting | ||
@@ -80,1 +106,2 @@ | ||
| 5. Would two tasks fight over the same file at the same time? Merge or sequence them. | ||
| 6. Does every hard sub-problem show its alternatives, a single recommendation, and a `WAITING_APPROVAL` decision task? (A silently pre-decided architecture → fix.) |
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
578744
2.01%62
1.64%5580
1.84%266
0.76%