@papi-ai/server 0.7.50 → 0.7.52
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/dist/index.js +182 -56
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -13096,7 +13096,7 @@ var planPrepareCache = new PerCallerCache();
|
|
|
13096
13096
|
var planTool = {
|
|
13097
13097
|
name: "plan",
|
|
13098
13098
|
description: 'Run once per cycle to select tasks and generate BUILD HANDOFFs. Call after setup (first time) or after completing all builds AND running release for the previous cycle. Returns prioritised task recommendations with detailed implementation specs. NEVER call when unbuilt cycle tasks exist \u2014 build and release first. First call returns a planning prompt for you to execute (prepare phase). Then call again with mode "apply" and your output to write results. Use skip_handoffs=true for large backlogs \u2014 handoffs are then generated separately via `handoff_generate`.',
|
|
13099
|
-
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
13099
|
+
annotations: { title: "Plan Cycle", readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
13100
13100
|
inputSchema: {
|
|
13101
13101
|
type: "object",
|
|
13102
13102
|
properties: {
|
|
@@ -13641,15 +13641,34 @@ async function findSimilarTasks(adapter2, ideaTitle) {
|
|
|
13641
13641
|
return matches.sort((a, b2) => b2.coverage - a.coverage).slice(0, 3);
|
|
13642
13642
|
}
|
|
13643
13643
|
var AD_ALIGNMENT_OVERLAP_THRESHOLD = 3;
|
|
13644
|
+
var DOC_FREQ_CEILING = 0.35;
|
|
13645
|
+
function findUbiquitousWords(ads) {
|
|
13646
|
+
const live = ads.filter((a) => !a.superseded);
|
|
13647
|
+
const ubiquitous = /* @__PURE__ */ new Set();
|
|
13648
|
+
if (live.length < 5) return ubiquitous;
|
|
13649
|
+
const docFreq = /* @__PURE__ */ new Map();
|
|
13650
|
+
for (const ad of live) {
|
|
13651
|
+
for (const w of extractKeywords(`${ad.title} ${ad.body}`)) {
|
|
13652
|
+
docFreq.set(w, (docFreq.get(w) ?? 0) + 1);
|
|
13653
|
+
}
|
|
13654
|
+
}
|
|
13655
|
+
const ceiling = live.length * DOC_FREQ_CEILING;
|
|
13656
|
+
for (const [w, df] of docFreq) {
|
|
13657
|
+
if (df > ceiling) ubiquitous.add(w);
|
|
13658
|
+
}
|
|
13659
|
+
return ubiquitous;
|
|
13660
|
+
}
|
|
13644
13661
|
function findAdAlignmentMatches(ideaText, ads) {
|
|
13645
13662
|
const ideaKeywords = extractKeywords(ideaText);
|
|
13646
13663
|
if (ideaKeywords.size < AD_ALIGNMENT_OVERLAP_THRESHOLD) return [];
|
|
13664
|
+
const ubiquitous = findUbiquitousWords(ads);
|
|
13647
13665
|
const matches = [];
|
|
13648
13666
|
for (const ad of ads) {
|
|
13649
13667
|
if (ad.superseded) continue;
|
|
13650
13668
|
const adKeywords = extractKeywords(`${ad.title} ${ad.body}`);
|
|
13651
13669
|
let overlap = 0;
|
|
13652
13670
|
for (const w of ideaKeywords) {
|
|
13671
|
+
if (ubiquitous.has(w)) continue;
|
|
13653
13672
|
if (adKeywords.has(w)) overlap++;
|
|
13654
13673
|
}
|
|
13655
13674
|
if (overlap >= AD_ALIGNMENT_OVERLAP_THRESHOLD) {
|
|
@@ -15494,7 +15513,7 @@ var reviewPrepareCache = new PerCallerCache();
|
|
|
15494
15513
|
var strategyReviewTool = {
|
|
15495
15514
|
name: "strategy_review",
|
|
15496
15515
|
description: 'Run a Strategy Review \u2014 assesses project direction, velocity, and Active Decisions. Produces recommendations and potential AD updates that feed into the next plan. Offered every 5 cycles; hard-blocked at 7+ overdue cycles. Run it in your current conversation \u2014 only start a fresh one if you are genuinely under context pressure (your host just compacted, you are near the context limit, or the session is heavy with build context), not just because a review is next. First call returns a review prompt for you to execute (prepare phase). Then call again with mode "apply" and your output. Pass `force: true` to run before the cadence gate.',
|
|
15497
|
-
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
15516
|
+
annotations: { title: "Run Strategy Review", readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
15498
15517
|
inputSchema: {
|
|
15499
15518
|
type: "object",
|
|
15500
15519
|
properties: {
|
|
@@ -15531,7 +15550,7 @@ var strategyReviewTool = {
|
|
|
15531
15550
|
var strategyAgendaTool = {
|
|
15532
15551
|
name: "strategy_agenda",
|
|
15533
15552
|
description: 'Queue topics for the next strategy review. Topics surface as input in the next `strategy_review` prepare phase and are automatically marked as addressed after the review completes. Two modes: "add" to queue a topic, "list" to see pending topics. Use this when you spot a strategic question during a build \u2014 capture the topic now instead of losing it.',
|
|
15534
|
-
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
15553
|
+
annotations: { title: "Strategy Agenda", readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
15535
15554
|
inputSchema: {
|
|
15536
15555
|
type: "object",
|
|
15537
15556
|
properties: {
|
|
@@ -15559,7 +15578,7 @@ var strategyAgendaTool = {
|
|
|
15559
15578
|
var strategyChangeTool = {
|
|
15560
15579
|
name: "strategy_change",
|
|
15561
15580
|
description: 'Apply a strategic shift to the project. Three modes: "capture" for lightweight mid-conversation decision capture (no LLM round-trip), "prepare" to get a change prompt for full analysis, "apply" to persist analysis output. Use "capture" when you detect a strategic decision in conversation and want to persist it quickly without disrupting the build flow. In "capture" mode, pass north_star to directly set/update the project North Star (no decision text needed).',
|
|
15562
|
-
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
15581
|
+
annotations: { title: "Change Strategy", readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
15563
15582
|
inputSchema: {
|
|
15564
15583
|
type: "object",
|
|
15565
15584
|
properties: {
|
|
@@ -16018,7 +16037,7 @@ async function archiveTasks(adapter2, phases, statuses) {
|
|
|
16018
16037
|
var boardViewTool = {
|
|
16019
16038
|
name: "board_view",
|
|
16020
16039
|
description: 'View the Board. To find a SPECIFIC task or subset, FILTER FIRST \u2014 do not dump the whole board: pass task_id for one task (full detail), query="<text>" for a title/notes substring match, or cycle=<n> for one cycle. Combine with status/phase. By default shows active tasks only (excludes Done/Cancelled), sorted by priority, limited to 50; titles are truncated in the table (single-task lookup shows the full title). Use status="all" to see everything, mode="summary" for counts only. Does not call the Anthropic API.',
|
|
16021
|
-
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
16040
|
+
annotations: { title: "View Board", readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
16022
16041
|
inputSchema: {
|
|
16023
16042
|
type: "object",
|
|
16024
16043
|
properties: {
|
|
@@ -16062,7 +16081,7 @@ var boardViewTool = {
|
|
|
16062
16081
|
var boardDeprioritiseTool = {
|
|
16063
16082
|
name: "board_deprioritise",
|
|
16064
16083
|
description: `Remove a task from the current cycle. Four actions: "backlog" (not now, maybe later \u2014 preserves handoff), "defer" (valid but premature \u2014 hidden from planner), "block" (waiting on external dependency \u2014 visible on board but skipped by planner), "cancel" (don't want this \u2014 permanently closed with reason). When a user rejects a task, ALWAYS ask which action they want. Does not call the Anthropic API.`,
|
|
16065
|
-
annotations: { readOnlyHint: false, destructiveHint: true },
|
|
16084
|
+
annotations: { title: "Deprioritise Task", readOnlyHint: false, destructiveHint: true, openWorldHint: false },
|
|
16066
16085
|
inputSchema: {
|
|
16067
16086
|
type: "object",
|
|
16068
16087
|
properties: {
|
|
@@ -16107,7 +16126,7 @@ var boardDeprioritiseTool = {
|
|
|
16107
16126
|
var boardArchiveTool = {
|
|
16108
16127
|
name: "board_archive",
|
|
16109
16128
|
description: "Archive tasks from the Board to the archive file. When both phase and status are provided, only tasks matching BOTH are archived (AND logic). When only one is provided, all matching tasks are archived. Does not call the Anthropic API.",
|
|
16110
|
-
annotations: { readOnlyHint: false, destructiveHint: true },
|
|
16129
|
+
annotations: { title: "Archive Task", readOnlyHint: false, destructiveHint: true, openWorldHint: false },
|
|
16111
16130
|
inputSchema: {
|
|
16112
16131
|
type: "object",
|
|
16113
16132
|
properties: {
|
|
@@ -16126,7 +16145,7 @@ var boardArchiveTool = {
|
|
|
16126
16145
|
var boardEditTool = {
|
|
16127
16146
|
name: "board_edit",
|
|
16128
16147
|
description: "Edit fields on an existing task. Supports title, priority, complexity, module, epic, phase, notes (with notes_mode for append/replace/clear), status, maturity, and cycle (number or null). Pass task_id plus any fields to update. Does not call the Anthropic API.",
|
|
16129
|
-
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
16148
|
+
annotations: { title: "Edit Task", readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
16130
16149
|
inputSchema: {
|
|
16131
16150
|
type: "object",
|
|
16132
16151
|
properties: {
|
|
@@ -18069,7 +18088,7 @@ async function ensureMcpJsonGitignored(projectRoot) {
|
|
|
18069
18088
|
var setupTool = {
|
|
18070
18089
|
name: "setup",
|
|
18071
18090
|
description: 'Create a new PAPI-tracked project \u2014 generates your Product Brief, Active Decisions, and CLAUDE.md workflow instructions. Run after configuring your MCP credentials (via `init` or manually from getpapi.ai). Only project_name is required \u2014 description and target_users are derived from README, package.json, and commit history when omitted. Set existing_project: true to adopt an existing codebase. ADOPTING AN EXISTING PROJECT OVER A REMOTE/HOSTED CONNECTOR (no local stdio install): PAPI cannot read your filesystem, so YOU (the client) must gather a `codebase_scan` and pass it in \u2014 list top-level dirs/files, the package manifest, the README (first ~3000 chars), and recent commit subjects. Without it, adoption falls back to asking for description/target_users. On a local stdio install PAPI scans the tree itself, so `codebase_scan` is optional there. First call returns prompts (prepare phase), then call again with mode "apply" and your outputs. After setup, run `plan` to start your first cycle.',
|
|
18072
|
-
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
18091
|
+
annotations: { title: "Set Up Project", readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
18073
18092
|
inputSchema: {
|
|
18074
18093
|
type: "object",
|
|
18075
18094
|
properties: {
|
|
@@ -19354,7 +19373,7 @@ async function postReleaseToX(version, cycleClosed) {
|
|
|
19354
19373
|
var releaseTool = {
|
|
19355
19374
|
name: "release",
|
|
19356
19375
|
description: "Cut a versioned release \u2014 creates a git tag, generates CHANGELOG.md, and pushes to remote. Pass skipVersion=true to update CHANGELOG and close the cycle without creating a tag or bumping version numbers.",
|
|
19357
|
-
annotations: { readOnlyHint: false, destructiveHint: true },
|
|
19376
|
+
annotations: { title: "Cut Release", readOnlyHint: false, destructiveHint: true, openWorldHint: false },
|
|
19358
19377
|
inputSchema: {
|
|
19359
19378
|
type: "object",
|
|
19360
19379
|
properties: {
|
|
@@ -20591,15 +20610,16 @@ async function completeBuild(adapter2, config2, taskId, input, options = {}, cli
|
|
|
20591
20610
|
const adIds = report.relatedDecisions ?? [];
|
|
20592
20611
|
const extractLearning = (text, category) => {
|
|
20593
20612
|
if (!text || text === "None" || text.trim().length === 0) return;
|
|
20594
|
-
const dotIdx = text.indexOf(". ");
|
|
20595
|
-
const summary = dotIdx > 0 && dotIdx < 120 ? text.slice(0, dotIdx + 1) : text.slice(0, 120);
|
|
20596
|
-
const tags = [];
|
|
20597
|
-
if (taskModule) tags.push(taskModule.toLowerCase());
|
|
20598
20613
|
let severity;
|
|
20599
20614
|
if (category === "issue") {
|
|
20600
20615
|
const sevMatch = text.match(/^(P[0-3])[\s:]/);
|
|
20601
20616
|
if (sevMatch) severity = sevMatch[1];
|
|
20602
20617
|
}
|
|
20618
|
+
const body = severity ? text.replace(/^P[0-3][\s:]+/, "").trim() : text.trim();
|
|
20619
|
+
const dotIdx = body.indexOf(". ");
|
|
20620
|
+
const summary = dotIdx > 0 ? body.slice(0, dotIdx + 1) : body;
|
|
20621
|
+
const tags = [];
|
|
20622
|
+
if (taskModule) tags.push(taskModule.toLowerCase());
|
|
20603
20623
|
learnings.push({
|
|
20604
20624
|
taskId: task.id,
|
|
20605
20625
|
cycleNumber,
|
|
@@ -21000,7 +21020,7 @@ import { randomUUID as randomUUID12 } from "crypto";
|
|
|
21000
21020
|
var docRegisterTool = {
|
|
21001
21021
|
name: "doc_register",
|
|
21002
21022
|
description: "Register or update a document in the doc registry. Called after finalising a research/planning doc, or when build_execute detects unregistered docs. Stores metadata and structured summary \u2014 not full content. Re-registering an existing doc updates its summary, tags, actions, type, and status (upsert). Visibility and owner are not changed on re-register.",
|
|
21003
|
-
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
21023
|
+
annotations: { title: "Register Doc", readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
21004
21024
|
inputSchema: {
|
|
21005
21025
|
type: "object",
|
|
21006
21026
|
properties: {
|
|
@@ -21033,7 +21053,7 @@ var docRegisterTool = {
|
|
|
21033
21053
|
var docSearchTool = {
|
|
21034
21054
|
name: "doc_search",
|
|
21035
21055
|
description: "Search the doc registry for documents by type, tags, keyword, or pending actions. Returns summaries, not full content. Use for context gathering in plan, strategy review, and idea dedup.",
|
|
21036
|
-
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
21056
|
+
annotations: { title: "Search Docs", readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
21037
21057
|
inputSchema: {
|
|
21038
21058
|
type: "object",
|
|
21039
21059
|
properties: {
|
|
@@ -21051,7 +21071,7 @@ var docSearchTool = {
|
|
|
21051
21071
|
var docScanTool = {
|
|
21052
21072
|
name: "doc_scan",
|
|
21053
21073
|
description: "Scan docs/ and plans directories for unregistered .md files. Returns a list of files not yet in the doc registry. Use this to find docs that need registration.",
|
|
21054
|
-
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
21074
|
+
annotations: { title: "Scan Docs", readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
21055
21075
|
inputSchema: {
|
|
21056
21076
|
type: "object",
|
|
21057
21077
|
properties: {
|
|
@@ -21298,7 +21318,7 @@ async function handleDocScan(adapter2, config2, args) {
|
|
|
21298
21318
|
var docActionPromoteTool = {
|
|
21299
21319
|
name: "doc_action_promote",
|
|
21300
21320
|
description: "Promote a single pending action from a registered doc into a Backlog task. The new task gets a `Reference:` line pointing to the source doc, and the doc action is marked resolved with `linkedTaskId` set. Use to close the research-to-action loop \u2014 turn unactioned findings into trackable cycle work. Identify the doc by `doc_path` (preferred) or `doc_id`, and the action by 0-based `action_index` (as listed in `doc_search` output).",
|
|
21301
|
-
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
21321
|
+
annotations: { title: "Promote Doc Action", readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
21302
21322
|
inputSchema: {
|
|
21303
21323
|
type: "object",
|
|
21304
21324
|
properties: {
|
|
@@ -21397,7 +21417,7 @@ init_git();
|
|
|
21397
21417
|
var buildListTool = {
|
|
21398
21418
|
name: "build_list",
|
|
21399
21419
|
description: "List cycle tasks that have BUILD HANDOFFs ready for execution. Shows task ID, title, status, priority, and complexity. In Progress tasks appear first, then Backlog. Does not call the Anthropic API.",
|
|
21400
|
-
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
21420
|
+
annotations: { title: "List Builds", readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
21401
21421
|
inputSchema: {
|
|
21402
21422
|
type: "object",
|
|
21403
21423
|
properties: {
|
|
@@ -21412,7 +21432,7 @@ var buildListTool = {
|
|
|
21412
21432
|
var buildDescribeTool = {
|
|
21413
21433
|
name: "build_describe",
|
|
21414
21434
|
description: "Show the full BUILD HANDOFF for a specific task, including scope, acceptance criteria, and implementation guidance. Does not call the Anthropic API.",
|
|
21415
|
-
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
21435
|
+
annotations: { title: "Describe Build", readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
21416
21436
|
inputSchema: {
|
|
21417
21437
|
type: "object",
|
|
21418
21438
|
properties: {
|
|
@@ -21427,7 +21447,7 @@ var buildDescribeTool = {
|
|
|
21427
21447
|
var buildExecuteTool = {
|
|
21428
21448
|
name: "build_execute",
|
|
21429
21449
|
description: "Start or complete a build task. Call with just task_id to start (returns BUILD HANDOFF, creates feature branch, marks In Progress). After implementing the task, you MUST call build_execute again with all report fields (completed, effort, estimated_effort, surprises, discovered_issues, architecture_notes) to finish \u2014 do not wait for user confirmation between start and complete. Never call on tasks that are already In Review or Done. Does not call the Anthropic API. Set light=true to skip branch/PR creation (commits to current branch). Set PAPI_LIGHT_MODE=true in env to default all builds to light mode.",
|
|
21430
|
-
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
21450
|
+
annotations: { title: "Run Build", readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
21431
21451
|
inputSchema: {
|
|
21432
21452
|
type: "object",
|
|
21433
21453
|
properties: {
|
|
@@ -21541,7 +21561,7 @@ var buildExecuteTool = {
|
|
|
21541
21561
|
var buildCancelTool = {
|
|
21542
21562
|
name: "build_cancel",
|
|
21543
21563
|
description: "Cancel a build task with a reason. Sets the task status to Cancelled and records the closure reason. Does not call the Anthropic API.",
|
|
21544
|
-
annotations: { readOnlyHint: false, destructiveHint: true },
|
|
21564
|
+
annotations: { title: "Cancel Build", readOnlyHint: false, destructiveHint: true, openWorldHint: false },
|
|
21545
21565
|
inputSchema: {
|
|
21546
21566
|
type: "object",
|
|
21547
21567
|
properties: {
|
|
@@ -22089,7 +22109,7 @@ Reason: ${result.reason}`);
|
|
|
22089
22109
|
init_git();
|
|
22090
22110
|
var ideaTool = {
|
|
22091
22111
|
name: "idea",
|
|
22092
|
-
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
22112
|
+
annotations: { title: "Capture Idea", readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
22093
22113
|
description: "Capture an idea as a Backlog task. The next plan run will triage and scope it. Use anytime to log bugs, feature requests, or improvements without interrupting the current cycle. IMPORTANT: If this idea originates from a research or planning session, you MUST include a Reference: line in notes pointing to the source doc. Without it, the planner has no context and will misinterpret the intent. Does not call the Anthropic API.",
|
|
22094
22114
|
inputSchema: {
|
|
22095
22115
|
type: "object",
|
|
@@ -22306,7 +22326,7 @@ function collectDiagnostics(config2) {
|
|
|
22306
22326
|
var bugTool = {
|
|
22307
22327
|
name: "bug",
|
|
22308
22328
|
description: `Report a bug OR submit an idea. Routing: a bug about PAPI itself (a PAPI tool/MCP error, the connector, a handoff/cycle problem) auto-submits UPSTREAM to PAPI maintainers with diagnostics \u2014 you do NOT need to set report=true for these. A bug in the user's OWN project auto-files as a Backlog task on their board. IMPORTANT: report=true is ONLY for a genuine PAPI-product defect \u2014 it is NOT the catch-all for "not about my app". A bug in the user's harness/editor/OS/git/other tooling (e.g. Claude Code, Codex, VS Code, a shell command) is NOT a PAPI bug: file it on the user's own board (report=false / default) or that tool's own tracker, never upstream. Override the routing explicitly: report=true forces upstream (PAPI-product only), report=false forces the user's own board. Set \`type\` ("bug"/"idea") and optional notify-when-fixed / contact-ok consent for upstream submissions. Does not call the Anthropic API.`,
|
|
22309
|
-
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
22329
|
+
annotations: { title: "Report Bug", readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
22310
22330
|
inputSchema: {
|
|
22311
22331
|
type: "object",
|
|
22312
22332
|
properties: {
|
|
@@ -22563,7 +22583,7 @@ function inferTaskType(description) {
|
|
|
22563
22583
|
var adHocTool = {
|
|
22564
22584
|
name: "ad_hoc",
|
|
22565
22585
|
description: "Record work done outside the normal cycle. Creates a Done task with a lightweight build report, or associates work with an existing task if task_id is provided (without changing task status \u2014 use build_execute for status transitions). Use for quick fixes, bug patches, or ad-hoc changes. Does not call the Anthropic API.",
|
|
22566
|
-
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
22586
|
+
annotations: { title: "Record Ad-Hoc Work", readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
22567
22587
|
inputSchema: {
|
|
22568
22588
|
type: "object",
|
|
22569
22589
|
properties: {
|
|
@@ -23053,7 +23073,7 @@ async function applyReconcile(adapter2, corrections) {
|
|
|
23053
23073
|
var boardReconcileTool = {
|
|
23054
23074
|
name: "board_reconcile",
|
|
23055
23075
|
description: 'Holistic board review \u2014 backlog + deferred tasks in one pass. Surfaces strategic context (ADs, phases, docs), grouping signals, merge candidates, priority drift, and stale tasks. "prepare" assembles context for you to analyse; "apply" commits your decisions after user confirmation. Does not call the Anthropic API.',
|
|
23056
|
-
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
23076
|
+
annotations: { title: "Reconcile Board", readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
23057
23077
|
inputSchema: {
|
|
23058
23078
|
type: "object",
|
|
23059
23079
|
properties: {
|
|
@@ -23546,7 +23566,7 @@ ${diffBlock}`;
|
|
|
23546
23566
|
var reviewListTool = {
|
|
23547
23567
|
name: "review_list",
|
|
23548
23568
|
description: "List tasks ready for your sign-off \u2014 shows completed builds waiting for approval or feedback. Does not call the Anthropic API.",
|
|
23549
|
-
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
23569
|
+
annotations: { title: "List Reviews", readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
23550
23570
|
inputSchema: {
|
|
23551
23571
|
type: "object",
|
|
23552
23572
|
properties: {
|
|
@@ -23561,7 +23581,7 @@ var reviewListTool = {
|
|
|
23561
23581
|
var reviewSubmitTool = {
|
|
23562
23582
|
name: "review_submit",
|
|
23563
23583
|
description: "Record a review verdict on a completed build (build-acceptance) or task plan (handoff-review). ALWAYS ask the human for their verdict before calling \u2014 never auto-submit without human input. Accept moves the task to Done, request-changes sends it back for rework, reject discards the build. Updates task status based on the verdict. On handoff-review with suggested changes, returns a prompt to revise the BUILD HANDOFF.\n\nDO NOT use this tool as a substitute for review_list. If you need to see what is pending review, call review_list first. If review_list is unavailable in your tool set, STOP and tell the human their MCP integration is incomplete rather than guessing at the next pending task. (SUP-2026-010.)",
|
|
23564
|
-
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
23584
|
+
annotations: { title: "Submit Review", readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
23565
23585
|
inputSchema: {
|
|
23566
23586
|
type: "object",
|
|
23567
23587
|
properties: {
|
|
@@ -24113,7 +24133,7 @@ ${statusNote}${autoReviewNote}${securityNote}${unblockNote}${docClosureNote}${re
|
|
|
24113
24133
|
var reviewClaimTool = {
|
|
24114
24134
|
name: "review_claim",
|
|
24115
24135
|
description: "Claim a Pending Review from the shared cross-user review queue so you are the one reviewing it. Atomic first-claim-wins \u2014 two reviewers cannot grab the same build. After claiming, run review_submit to record your verdict. Owner-or-active-member only. Does not call the Anthropic API.",
|
|
24116
|
-
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
24136
|
+
annotations: { title: "Claim Review", readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
24117
24137
|
inputSchema: {
|
|
24118
24138
|
type: "object",
|
|
24119
24139
|
properties: {
|
|
@@ -24178,7 +24198,7 @@ import path5 from "path";
|
|
|
24178
24198
|
var initTool = {
|
|
24179
24199
|
name: "init",
|
|
24180
24200
|
description: "Write the MCP config file that connects this project to PAPI. Generates .mcp.json (Claude Code default) or the equivalent for Cursor, VS Code, Windsurf, OpenCode, Amazon Q, Kilo Code, Gemini CLI, Codex CLI, or Hermes Agent. Config-only \u2014 does not create any project data. Run this first, then run `setup` to create your PAPI project.",
|
|
24181
|
-
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
24201
|
+
annotations: { title: "Initialise Project", readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
24182
24202
|
inputSchema: {
|
|
24183
24203
|
type: "object",
|
|
24184
24204
|
properties: {
|
|
@@ -25087,6 +25107,104 @@ function formatUnblockSection(candidates) {
|
|
|
25087
25107
|
return lines.join("\n");
|
|
25088
25108
|
}
|
|
25089
25109
|
|
|
25110
|
+
// src/lib/deferred-gate.ts
|
|
25111
|
+
var GATE_PHRASES = [
|
|
25112
|
+
"depends on",
|
|
25113
|
+
"depends upon",
|
|
25114
|
+
"gated on",
|
|
25115
|
+
"gated behind",
|
|
25116
|
+
"blocked on",
|
|
25117
|
+
"blocked by",
|
|
25118
|
+
"waiting on",
|
|
25119
|
+
"waiting for",
|
|
25120
|
+
"pending",
|
|
25121
|
+
"once",
|
|
25122
|
+
"after",
|
|
25123
|
+
"until",
|
|
25124
|
+
"requires",
|
|
25125
|
+
"needs",
|
|
25126
|
+
"pull condition",
|
|
25127
|
+
"unblocked by"
|
|
25128
|
+
];
|
|
25129
|
+
var CONTEXT_WINDOW = 60;
|
|
25130
|
+
var TASK_REF2 = /\btask-\d+\b/gi;
|
|
25131
|
+
var MAX_PER_BUCKET = 8;
|
|
25132
|
+
function extractGatedTaskRefs(notes) {
|
|
25133
|
+
if (!notes) return [];
|
|
25134
|
+
const out = [];
|
|
25135
|
+
const seen = /* @__PURE__ */ new Set();
|
|
25136
|
+
for (const m of notes.matchAll(TASK_REF2)) {
|
|
25137
|
+
const ref = m[0].toLowerCase();
|
|
25138
|
+
if (seen.has(ref)) continue;
|
|
25139
|
+
const start = Math.max(0, (m.index ?? 0) - CONTEXT_WINDOW);
|
|
25140
|
+
const before = notes.slice(start, m.index).toLowerCase();
|
|
25141
|
+
const hit = GATE_PHRASES.find((p) => before.includes(p));
|
|
25142
|
+
if (!hit) continue;
|
|
25143
|
+
seen.add(ref);
|
|
25144
|
+
const evidence = notes.slice(start, (m.index ?? 0) + m[0].length).trim();
|
|
25145
|
+
out.push({ ref, evidence: evidence.length > 90 ? `\u2026${evidence.slice(-90)}` : evidence });
|
|
25146
|
+
}
|
|
25147
|
+
return out;
|
|
25148
|
+
}
|
|
25149
|
+
async function findDeferredGates(adapter2) {
|
|
25150
|
+
const empty = { unblock: [], zombie: [] };
|
|
25151
|
+
let allTasks = [];
|
|
25152
|
+
try {
|
|
25153
|
+
allTasks = await adapter2.queryBoard();
|
|
25154
|
+
} catch {
|
|
25155
|
+
return empty;
|
|
25156
|
+
}
|
|
25157
|
+
const deferred = allTasks.filter((t) => t.status === "Deferred");
|
|
25158
|
+
if (deferred.length === 0) return empty;
|
|
25159
|
+
const byId = /* @__PURE__ */ new Map();
|
|
25160
|
+
for (const t of allTasks) {
|
|
25161
|
+
if (t.displayId) byId.set(t.displayId.toLowerCase(), t);
|
|
25162
|
+
}
|
|
25163
|
+
const sweep = { unblock: [], zombie: [] };
|
|
25164
|
+
for (const task of deferred) {
|
|
25165
|
+
for (const { ref, evidence } of extractGatedTaskRefs(task.notes ?? "")) {
|
|
25166
|
+
const self = task.displayId?.toLowerCase();
|
|
25167
|
+
if (self && ref === self) continue;
|
|
25168
|
+
const upstream = byId.get(ref);
|
|
25169
|
+
if (!upstream) continue;
|
|
25170
|
+
if (upstream.status !== "Done" && upstream.status !== "Cancelled") continue;
|
|
25171
|
+
const gate = {
|
|
25172
|
+
taskId: task.displayId ?? task.id,
|
|
25173
|
+
taskTitle: task.title,
|
|
25174
|
+
upstreamId: upstream.displayId ?? upstream.id,
|
|
25175
|
+
upstreamTitle: upstream.title,
|
|
25176
|
+
upstreamStatus: upstream.status,
|
|
25177
|
+
evidence
|
|
25178
|
+
};
|
|
25179
|
+
const bucket = upstream.status === "Done" ? sweep.unblock : sweep.zombie;
|
|
25180
|
+
if (bucket.length < MAX_PER_BUCKET) bucket.push(gate);
|
|
25181
|
+
break;
|
|
25182
|
+
}
|
|
25183
|
+
}
|
|
25184
|
+
return sweep;
|
|
25185
|
+
}
|
|
25186
|
+
function formatDeferredGateSection(sweep) {
|
|
25187
|
+
if (sweep.unblock.length === 0 && sweep.zombie.length === 0) return "";
|
|
25188
|
+
const lines = ["## Deferred-Gate Sweep"];
|
|
25189
|
+
if (sweep.unblock.length > 0) {
|
|
25190
|
+
lines.push("");
|
|
25191
|
+
lines.push(`**Unblock candidates (${sweep.unblock.length})** \u2014 the upstream task is Done, so the gate has cleared. Promote with \`board_edit\` \u2192 Backlog.`);
|
|
25192
|
+
for (const g of sweep.unblock) {
|
|
25193
|
+
lines.push(`- **${g.taskId}** (${g.taskTitle}) \u2014 gated on **${g.upstreamId}** which is now Done \u2705`);
|
|
25194
|
+
}
|
|
25195
|
+
}
|
|
25196
|
+
if (sweep.zombie.length > 0) {
|
|
25197
|
+
lines.push("");
|
|
25198
|
+
lines.push(`**Zombie candidates (${sweep.zombie.length})** \u2014 the upstream task was CANCELLED, so this gate can never clear. Cancel or re-scope.`);
|
|
25199
|
+
for (const g of sweep.zombie) {
|
|
25200
|
+
lines.push(`- **${g.taskId}** (${g.taskTitle}) \u2014 gated on **${g.upstreamId}** which was Cancelled \u274C`);
|
|
25201
|
+
}
|
|
25202
|
+
}
|
|
25203
|
+
lines.push("");
|
|
25204
|
+
lines.push("_Advisory only \u2014 nothing was changed. Gates are read from freetext notes, so check the reference before acting._");
|
|
25205
|
+
return lines.join("\n");
|
|
25206
|
+
}
|
|
25207
|
+
|
|
25090
25208
|
// src/tools/agent-list.ts
|
|
25091
25209
|
import { readdir as readdir2, readFile as readFile7 } from "fs/promises";
|
|
25092
25210
|
import { join as join14 } from "path";
|
|
@@ -25129,7 +25247,7 @@ async function listAgents(projectRoot) {
|
|
|
25129
25247
|
var agentListTool = {
|
|
25130
25248
|
name: "agent_list",
|
|
25131
25249
|
description: "List the sub-agents discovered in the project's `.claude/agents/*.md` files (read-only). Returns each agent's name and description so you can see which specialised sub-agents are available before dispatching one via the Task/Agent tool. Discovery only \u2014 does not invoke or manage agents.",
|
|
25132
|
-
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
25250
|
+
annotations: { title: "List Agents", readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
25133
25251
|
inputSchema: {
|
|
25134
25252
|
type: "object",
|
|
25135
25253
|
properties: {
|
|
@@ -25308,7 +25426,7 @@ async function runWithLimit(concurrency, tasks) {
|
|
|
25308
25426
|
var orientTool = {
|
|
25309
25427
|
name: "orient",
|
|
25310
25428
|
description: "Session orientation \u2014 run this FIRST at session start before any other tool. Single call that replaces build_list + health. Returns: cycle number, task counts by status, in-progress/in-review tasks, strategy review cadence, velocity snapshot, recommended next action, and a release reminder when all cycle tasks are Done but release has not run. Read-only, does not modify any files. PAPI detects build capability from the connecting harness (clientInfo); pass `environment` only to override that detection for git-dependent recommendations (build_execute, release, review_submit).",
|
|
25311
|
-
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
25429
|
+
annotations: { title: "Orient Session", readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
25312
25430
|
inputSchema: {
|
|
25313
25431
|
type: "object",
|
|
25314
25432
|
properties: {
|
|
@@ -25332,6 +25450,7 @@ var orientTool = {
|
|
|
25332
25450
|
var papiTool = {
|
|
25333
25451
|
...orientTool,
|
|
25334
25452
|
name: "papi",
|
|
25453
|
+
annotations: { title: "PAPI Status", readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
25335
25454
|
description: 'Say "papi" to check in with Papi \u2014 an alias for `orient`. Run this FIRST at session start: it returns your cycle number, task counts, in-progress/in-review work, strategy-review cadence, a velocity snapshot, and the recommended next action. Identical to `orient` (same inputs, same output); use whichever name you prefer. Read-only.'
|
|
25336
25455
|
};
|
|
25337
25456
|
function countStalledP1(warnings) {
|
|
@@ -26196,6 +26315,17 @@ ${versionDrift}` : "";
|
|
|
26196
26315
|
${section}`;
|
|
26197
26316
|
} catch {
|
|
26198
26317
|
}
|
|
26318
|
+
let deferredGateNote = "";
|
|
26319
|
+
if (deepHousekeeping) {
|
|
26320
|
+
try {
|
|
26321
|
+
const sweep = await tracked("deferred-gates", () => findDeferredGates(adapter2))();
|
|
26322
|
+
const section = formatDeferredGateSection(sweep);
|
|
26323
|
+
if (section) deferredGateNote = `
|
|
26324
|
+
|
|
26325
|
+
${section}`;
|
|
26326
|
+
} catch {
|
|
26327
|
+
}
|
|
26328
|
+
}
|
|
26199
26329
|
tracker.mark("format-summary");
|
|
26200
26330
|
const subAgents = await listAgents(config2.projectRoot);
|
|
26201
26331
|
const [teamSummaryLine, releaseHistoryLine] = await Promise.all([
|
|
@@ -26204,7 +26334,7 @@ ${section}`;
|
|
|
26204
26334
|
]);
|
|
26205
26335
|
const teamSummary = [teamSummaryLine, releaseHistoryLine].filter(Boolean).join("\n") || void 0;
|
|
26206
26336
|
const deepHint = deepHousekeeping ? "" : "\n\n*Tip: pass `full: true` for Research Signals + version-drift, or `deep_housekeeping: true` to also check orphaned branches, merged-but-In-Progress tasks, unrecorded commits, unregistered docs, and stale skill forks (implies `full`).*";
|
|
26207
|
-
return textResponse(projectBannerNote + formatOrientSummary(healthResult, buildInfo, hierarchy, latestTag, config2.projectRoot, environment, subAgents, projectName, teamSummary, clientName) + unblockNote + feedbackResolvedNote + alertsNote + ttfvNote + reconciliationNote + mergedInProgressNote + unrecordedNote + unregisteredDocsNote + staleSkillsNote + researchSignalsNote + recsNote + pendingReviewNote + patternsNote + unactionedIssuesNote + skillProposalsNote + sessionGuidanceNote + versionNote + enrichmentNote + deliveryShapeNote + preBuildCheckNote + deepHint + enrichmentFilesSection);
|
|
26337
|
+
return textResponse(projectBannerNote + formatOrientSummary(healthResult, buildInfo, hierarchy, latestTag, config2.projectRoot, environment, subAgents, projectName, teamSummary, clientName) + unblockNote + deferredGateNote + feedbackResolvedNote + alertsNote + ttfvNote + reconciliationNote + mergedInProgressNote + unrecordedNote + unregisteredDocsNote + staleSkillsNote + researchSignalsNote + recsNote + pendingReviewNote + patternsNote + unactionedIssuesNote + skillProposalsNote + sessionGuidanceNote + versionNote + enrichmentNote + deliveryShapeNote + preBuildCheckNote + deepHint + enrichmentFilesSection);
|
|
26208
26338
|
} catch (err) {
|
|
26209
26339
|
const message = err instanceof Error ? err.message : String(err);
|
|
26210
26340
|
const isKnownFriendly = /^(Orient failed|Project not found|No project|Setup required)/i.test(message);
|
|
@@ -26260,7 +26390,7 @@ function enrichClaudeMd(projectRoot, cycleNumber, adapterType, collector, client
|
|
|
26260
26390
|
var hierarchyUpdateTool = {
|
|
26261
26391
|
name: "hierarchy_update",
|
|
26262
26392
|
description: "Update the status of a phase, stage, or horizon in the project hierarchy (AD-14). Accepts a level (phase, stage, or horizon), a name or ID, and a new status. For stages, optionally set exit_criteria \u2014 a checklist defining when the stage is considered done. Does not call the Anthropic API.",
|
|
26263
|
-
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
26393
|
+
annotations: { title: "Update Hierarchy", readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
26264
26394
|
inputSchema: {
|
|
26265
26395
|
type: "object",
|
|
26266
26396
|
properties: {
|
|
@@ -26671,7 +26801,7 @@ async function applyZoomOut(adapter2, llmResponse, cycleNumber) {
|
|
|
26671
26801
|
var zoomOutTool = {
|
|
26672
26802
|
name: "zoom_out",
|
|
26673
26803
|
description: 'Run a Zoom-Out Retrospective \u2014 a higher-level meta-retrospective that sits above strategy reviews. Analyses the full project arc: every cycle, decision, and pivot. Use when you want to step back and see the big picture after many cycles. First call returns a prompt (prepare phase). Then call again with mode "apply" and your output.',
|
|
26674
|
-
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
26804
|
+
annotations: { title: "Zoom Out", readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
26675
26805
|
inputSchema: {
|
|
26676
26806
|
type: "object",
|
|
26677
26807
|
properties: {
|
|
@@ -26775,7 +26905,7 @@ ${result.userMessage}
|
|
|
26775
26905
|
var getSiblingAdsTool = {
|
|
26776
26906
|
name: "get_sibling_ads",
|
|
26777
26907
|
description: "Read Active Decisions from sibling PAPI projects that share the same Supabase instance. Requires PAPI_SIBLING_PROJECT_IDS env var (comma-separated project UUIDs). Returns ADs labelled by source project \u2014 useful for cross-project architectural alignment. pg adapter only \u2014 returns an error if using md or proxy adapter.",
|
|
26778
|
-
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
26908
|
+
annotations: { title: "Sibling Decisions", readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
26779
26909
|
inputSchema: {
|
|
26780
26910
|
type: "object",
|
|
26781
26911
|
properties: {
|
|
@@ -26852,7 +26982,7 @@ var handoffPrepareCache = new PerCallerCache();
|
|
|
26852
26982
|
var handoffGenerateTool = {
|
|
26853
26983
|
name: "handoff_generate",
|
|
26854
26984
|
description: "Generate BUILD HANDOFFs for cycle tasks that don't have one yet. Run after `plan` (with skip_handoffs=true) or to regenerate stale handoffs. Uses the prepare/apply pattern \u2014 first call returns a prompt, second call persists results.",
|
|
26855
|
-
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
26985
|
+
annotations: { title: "Generate Handoff", readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
26856
26986
|
inputSchema: {
|
|
26857
26987
|
type: "object",
|
|
26858
26988
|
properties: {
|
|
@@ -27108,7 +27238,7 @@ function buildSummary(task, taskCount) {
|
|
|
27108
27238
|
var scopeBriefTool = {
|
|
27109
27239
|
name: "scope_brief",
|
|
27110
27240
|
description: "Decompose a brief-class task (Large/XL, too large to build directly) into a structured scope document. Runs an LLM pass to produce sub-tasks, writes docs/scopes/<task-id>.md, registers it in the doc registry, and marks the source task as decomposed. Use before planning a cycle that includes brief-class tasks.",
|
|
27111
|
-
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
27241
|
+
annotations: { title: "Scope Brief", readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
27112
27242
|
inputSchema: {
|
|
27113
27243
|
type: "object",
|
|
27114
27244
|
properties: {
|
|
@@ -27157,7 +27287,7 @@ async function handleScopeBrief(adapter2, config2, args) {
|
|
|
27157
27287
|
var adViewTool = {
|
|
27158
27288
|
name: "ad_view",
|
|
27159
27289
|
description: "View one or all Active Decisions with full bodies. Use when you need to read the complete reasoning and evidence behind a specific AD before running strategy_change.",
|
|
27160
|
-
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
27290
|
+
annotations: { title: "View Decisions", readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
27161
27291
|
inputSchema: {
|
|
27162
27292
|
type: "object",
|
|
27163
27293
|
properties: {
|
|
@@ -27214,7 +27344,7 @@ ${formatted}`);
|
|
|
27214
27344
|
var learningActionTool = {
|
|
27215
27345
|
name: "learning_action",
|
|
27216
27346
|
description: `Mark a cycle learning as actioned (linking it to a task or idea) or list unactioned learnings. Use "mark" to close out a learning after you've submitted an idea or created a task for it. Use "list" to see which learnings from recent cycles still need follow-up.`,
|
|
27217
|
-
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
27347
|
+
annotations: { title: "Action Learning", readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
27218
27348
|
inputSchema: {
|
|
27219
27349
|
type: "object",
|
|
27220
27350
|
properties: {
|
|
@@ -27300,7 +27430,7 @@ Use \`learning_action mark\` or submit via \`idea\` to close these out.`
|
|
|
27300
27430
|
var discoveredIssueResolveTool = {
|
|
27301
27431
|
name: "discovered_issue_resolve",
|
|
27302
27432
|
description: 'Mark a discovered_issue (cycle_learnings row, category="issue") as resolved. Pass the learning_id you saw in orient / learning_action list output. The row stays in the database for history, but default reads exclude it. Use this when the underlying fix has actually landed \u2014 NOT when you just created a follow-up task (that is `learning_action mark` with action_taken="task_created"). Optional `note` is recorded as resolved_by.',
|
|
27303
|
-
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
27433
|
+
annotations: { title: "Resolve Issue", readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
27304
27434
|
inputSchema: {
|
|
27305
27435
|
type: "object",
|
|
27306
27436
|
properties: {
|
|
@@ -27399,7 +27529,7 @@ var NO_SUPPORT = "Project lifecycle tools require a hosted (proxy) or PostgreSQL
|
|
|
27399
27529
|
var projectCreateTool = {
|
|
27400
27530
|
name: "project_create",
|
|
27401
27531
|
description: 'Create an EMPTY PAPI project for the current workspace (no plan, no seeded backlog) and return its id. Idempotent: re-running in the same folder (or with the same name) returns the EXISTING project instead of creating a duplicate. Use when "set up papi here" / "create a project" and none matches this folder. No Anthropic API.',
|
|
27402
|
-
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
27532
|
+
annotations: { title: "Create Project", readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
27403
27533
|
inputSchema: {
|
|
27404
27534
|
type: "object",
|
|
27405
27535
|
properties: {
|
|
@@ -27445,7 +27575,7 @@ Run \`plan\` when you're ready to start a cycle.`
|
|
|
27445
27575
|
var projectListTool = {
|
|
27446
27576
|
name: "project_list",
|
|
27447
27577
|
description: "List the PAPI projects on your account (id, name, slug, mapped folder). Use to see which project you are about to write to, or to find the id/slug to pass to project_switch or the per-call `project` arg. No Anthropic API.",
|
|
27448
|
-
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
27578
|
+
annotations: { title: "List Projects", readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
27449
27579
|
inputSchema: {
|
|
27450
27580
|
type: "object",
|
|
27451
27581
|
properties: {
|
|
@@ -27476,7 +27606,7 @@ ${lines.join("\n")}`);
|
|
|
27476
27606
|
var projectSwitchTool = {
|
|
27477
27607
|
name: "project_switch",
|
|
27478
27608
|
description: 'Select a project you own by id or slug and map the current folder to it (sets papi_dir on local stdio). Use when "switch to golf" / "point papi at <project>". Fails closed if the project is not on your account. No Anthropic API.',
|
|
27479
|
-
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
27609
|
+
annotations: { title: "Switch Project", readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
27480
27610
|
inputSchema: {
|
|
27481
27611
|
type: "object",
|
|
27482
27612
|
properties: {
|
|
@@ -27511,7 +27641,7 @@ On hosted/remote sessions this is now your DEFAULT project \u2014 calls without
|
|
|
27511
27641
|
var contributorAddTool = {
|
|
27512
27642
|
name: "contributor_add",
|
|
27513
27643
|
description: "Add a contributor to the current project by email (owner-only). The person must already have a PAPI account. Grants cohort membership on project_contributors \u2014 contributors-tier visibility, no roles yet.",
|
|
27514
|
-
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
27644
|
+
annotations: { title: "Add Contributor", readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
27515
27645
|
inputSchema: {
|
|
27516
27646
|
type: "object",
|
|
27517
27647
|
properties: {
|
|
@@ -27523,7 +27653,7 @@ var contributorAddTool = {
|
|
|
27523
27653
|
var contributorRemoveTool = {
|
|
27524
27654
|
name: "contributor_remove",
|
|
27525
27655
|
description: "Remove a contributor from the current project by email (owner-only). Deletes their project_contributors row \u2014 they lose contributors-tier visibility.",
|
|
27526
|
-
annotations: { readOnlyHint: false, destructiveHint: true },
|
|
27656
|
+
annotations: { title: "Remove Contributor", readOnlyHint: false, destructiveHint: true, openWorldHint: false },
|
|
27527
27657
|
inputSchema: {
|
|
27528
27658
|
type: "object",
|
|
27529
27659
|
properties: {
|
|
@@ -27535,7 +27665,7 @@ var contributorRemoveTool = {
|
|
|
27535
27665
|
var contributorListTool = {
|
|
27536
27666
|
name: "contributor_list",
|
|
27537
27667
|
description: "List the current project's contributors (any project member). Shows each member's email, display name, role, and join date. Does not call the Anthropic API.",
|
|
27538
|
-
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
27668
|
+
annotations: { title: "List Contributors", readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
27539
27669
|
inputSchema: {
|
|
27540
27670
|
type: "object",
|
|
27541
27671
|
properties: {
|
|
@@ -27641,7 +27771,7 @@ async function handleContributorList(adapter2, config2, _args) {
|
|
|
27641
27771
|
var taskClaimTool = {
|
|
27642
27772
|
name: "task_claim",
|
|
27643
27773
|
description: "Claim a task from the shared org Pool into your personal backlog (assignee = you). Atomic first-claim-wins \u2014 a concurrent double-claim is impossible. Cascades the DEPENDS ON chain: claiming a task also claims its not-Done prerequisites; if any prerequisite is already claimed by another member the whole claim is refused (a build unit is never split across owners). Does not call the Anthropic API.",
|
|
27644
|
-
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
27774
|
+
annotations: { title: "Claim Task", readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
27645
27775
|
inputSchema: {
|
|
27646
27776
|
type: "object",
|
|
27647
27777
|
properties: {
|
|
@@ -27653,7 +27783,7 @@ var taskClaimTool = {
|
|
|
27653
27783
|
var taskUnclaimTool = {
|
|
27654
27784
|
name: "task_unclaim",
|
|
27655
27785
|
description: "Release a task you claimed back to the shared Pool (clears assignee). Claimer-only and pre-review \u2014 you cannot unclaim another member's task or one that has reached In Review/Done. Does not cascade. Does not call the Anthropic API.",
|
|
27656
|
-
annotations: { readOnlyHint: false, destructiveHint: true },
|
|
27786
|
+
annotations: { title: "Unclaim Task", readOnlyHint: false, destructiveHint: true, openWorldHint: false },
|
|
27657
27787
|
inputSchema: {
|
|
27658
27788
|
type: "object",
|
|
27659
27789
|
properties: {
|
|
@@ -27790,7 +27920,7 @@ async function handleTaskUnclaim(adapter2, config2, args) {
|
|
|
27790
27920
|
var taskMoveTool = {
|
|
27791
27921
|
name: "task_move",
|
|
27792
27922
|
description: "Move a task from the current project to another project you own. Reassigns the task a fresh id in the target (collision-free) and carries its build reports, comments, and history with it; the cycle assignment is cleared so it lands in the target project's backlog. You must own (or have write access to) BOTH projects. Destructive-ish and cross-project, so it requires confirm=true \u2014 without it you get a preview only. Does not call the Anthropic API.",
|
|
27793
|
-
annotations: { readOnlyHint: false, destructiveHint: true },
|
|
27923
|
+
annotations: { title: "Move Task", readOnlyHint: false, destructiveHint: true, openWorldHint: false },
|
|
27794
27924
|
inputSchema: {
|
|
27795
27925
|
type: "object",
|
|
27796
27926
|
properties: {
|
|
@@ -27977,7 +28107,7 @@ async function syncHarnessInventory(adapter2, config2, opts) {
|
|
|
27977
28107
|
var inventorySyncTool = {
|
|
27978
28108
|
name: "inventory_sync",
|
|
27979
28109
|
description: "Sync this project's harness inventory \u2014 skills, sub-agents, hooks, and MCP tools \u2014 to the database so the dashboard can surface it. Gated by a cheap change-fingerprint: a no-op when the harness hasn't changed since the last sync. Set force=true to re-scan and write regardless. Runs automatically at setup and release; use this for an explicit refresh after editing your harness.",
|
|
27980
|
-
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
28110
|
+
annotations: { title: "Sync Inventory", readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
27981
28111
|
inputSchema: {
|
|
27982
28112
|
type: "object",
|
|
27983
28113
|
properties: {
|
|
@@ -29215,11 +29345,7 @@ if (!isHttpMode) {
|
|
|
29215
29345
|
);
|
|
29216
29346
|
const errorMessage = setupError || "Unknown startup error";
|
|
29217
29347
|
server.setRequestHandler(ListToolsRequestSchema2, async () => ({
|
|
29218
|
-
tools: [
|
|
29219
|
-
name: "setup",
|
|
29220
|
-
description: "PAPI is not connected \u2014 run this tool for setup instructions.",
|
|
29221
|
-
inputSchema: { type: "object", properties: {}, required: [] }
|
|
29222
|
-
}]
|
|
29348
|
+
tools: [...PAPI_TOOLS]
|
|
29223
29349
|
}));
|
|
29224
29350
|
server.setRequestHandler(CallToolRequestSchema2, async () => ({
|
|
29225
29351
|
content: [{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@papi-ai/server",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.52",
|
|
4
4
|
"description": "PAPI MCP server — AI-powered sprint planning, build execution, and strategy review for software projects",
|
|
5
5
|
"license": "Elastic-2.0",
|
|
6
6
|
"mcpName": "io.github.getpapi/papi",
|