@papi-ai/server 0.7.84 → 0.7.85

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.
@@ -135,7 +135,21 @@ var init_dist = __esm({
135
135
  { key: "autoBranch", label: "Auto branch", description: "Creates a feature branch per task/cycle at build start.", step: "build" },
136
136
  { key: "autoCommit", label: "Auto commit", description: "Commits your work automatically when a build completes.", step: "build" },
137
137
  { key: "autoPush", label: "Auto push & PR", description: "Pushes the branch and opens a pull request on build complete.", step: "build" },
138
- { key: "papiMetaFraming", label: "PAPI self-referential framing", description: "Includes PAPI-meta build-discipline framing in handoff output.", step: "build" }
138
+ { key: "papiMetaFraming", label: "PAPI self-referential framing", description: "Includes PAPI-meta build-discipline framing in handoff output.", step: "build" },
139
+ // Editor-equal release. Two legitimate team shapes need opposite answers, so
140
+ // this is a PROJECT policy rather than a global rule:
141
+ //
142
+ // OFF (default) — an editor's release opens a CONTRIBUTOR PR and PAPI records
143
+ // the release when GitHub merges it. Right for an open//multi-contributor
144
+ // product where the project owner is the last gate before production.
145
+ // ON — an editor releases on exactly the owner's path. Right for a small team
146
+ // of trusted peers who each run whole cycles end to end, where routing every
147
+ // close back through one person is the bottleneck, not the safeguard.
148
+ //
149
+ // Defaults OFF so existing projects are byte-identical, and because widening who
150
+ // can ship to production must be a deliberate choice, never a silent upgrade.
151
+ // A VIEWER is denied either way — this moves the editor line only.
152
+ { key: "editorRelease", label: "Editors release like the owner", description: "Lets editors run a full release instead of opening a contributor PR.", step: "release", defaultEnabled: false }
139
153
  ];
140
154
  CAPABILITY_KEYS = CAPABILITY_REGISTRY.map((c) => c.key);
141
155
  HOSTED_APP_URL = "https://getpapi.ai";
@@ -171,6 +185,7 @@ __export(git_exports, {
171
185
  detectUnrecordedCommits: () => detectUnrecordedCommits,
172
186
  ensureLatestDevelop: () => ensureLatestDevelop,
173
187
  ensureTagAtHead: () => ensureTagAtHead,
188
+ findContributorReleasePullRequests: () => findContributorReleasePullRequests,
174
189
  findTaskCommitsOnBase: () => findTaskCommitsOnBase,
175
190
  getBranchDiff: () => getBranchDiff,
176
191
  getCommitFiles: () => getCommitFiles,
@@ -188,6 +203,7 @@ __export(git_exports, {
188
203
  getOriginRepoSlug: () => getOriginRepoSlug,
189
204
  getOriginUrl: () => getOriginUrl,
190
205
  getPathsDifferingFrom: () => getPathsDifferingFrom,
206
+ getPullRequestState: () => getPullRequestState,
191
207
  getPullRequestUrl: () => getPullRequestUrl,
192
208
  getRemoteBranchFiles: () => getRemoteBranchFiles,
193
209
  getRootCommitHash: () => getRootCommitHash,
@@ -1151,6 +1167,56 @@ function getPullRequestUrl(cwd, branch) {
1151
1167
  return null;
1152
1168
  }
1153
1169
  }
1170
+ function getPullRequestState(cwd, prUrl) {
1171
+ try {
1172
+ const output = execFileSync(
1173
+ "gh",
1174
+ ["pr", "view", prUrl, "--json", "url,state,mergedAt"],
1175
+ { cwd, encoding: "utf-8" }
1176
+ ).trim();
1177
+ if (!output) return null;
1178
+ const parsed = JSON.parse(output);
1179
+ if (!parsed.url || !["OPEN", "CLOSED", "MERGED"].includes(parsed.state ?? "")) return null;
1180
+ return {
1181
+ url: parsed.url,
1182
+ state: parsed.state,
1183
+ mergedAt: parsed.mergedAt ?? null
1184
+ };
1185
+ } catch {
1186
+ return null;
1187
+ }
1188
+ }
1189
+ function findContributorReleasePullRequests(cwd, cycle) {
1190
+ if (!Number.isInteger(cycle) || cycle <= 0) return [];
1191
+ try {
1192
+ const output = execFileSync(
1193
+ "gh",
1194
+ [
1195
+ "pr",
1196
+ "list",
1197
+ "--state",
1198
+ "all",
1199
+ "--limit",
1200
+ "20",
1201
+ "--search",
1202
+ `"Contributor release PR for cycle ${cycle}" in:body`,
1203
+ "--json",
1204
+ "url,state,mergedAt,headRefName"
1205
+ ],
1206
+ { cwd, encoding: "utf-8" }
1207
+ ).trim();
1208
+ if (!output) return [];
1209
+ const parsed = JSON.parse(output);
1210
+ return parsed.flatMap((pr) => pr.url && pr.headRefName && ["OPEN", "CLOSED", "MERGED"].includes(pr.state ?? "") ? [{
1211
+ url: pr.url,
1212
+ state: pr.state,
1213
+ mergedAt: pr.mergedAt ?? null,
1214
+ branch: pr.headRefName
1215
+ }] : []);
1216
+ } catch {
1217
+ return [];
1218
+ }
1219
+ }
1154
1220
  function squashMergePullRequest(cwd, branch) {
1155
1221
  const repo = getOriginRepoSlug(cwd);
1156
1222
  const baseArgs = ["pr", "merge", branch, "--squash", "--delete-branch"];
@@ -1518,6 +1584,10 @@ var init_proxy_adapter = __esm({
1518
1584
  "dismissRecommendation",
1519
1585
  "findPendingDocActionsForTask",
1520
1586
  "getActiveDecisions",
1587
+ "getContributorRole",
1588
+ "listContributorReleasePrs",
1589
+ "recordContributorReleasePr",
1590
+ "setContributorReleasePrStatus",
1521
1591
  "getActiveStage",
1522
1592
  "getBuildReportCountForTask",
1523
1593
  "getBuildReportsSince",
@@ -1657,7 +1727,7 @@ var init_proxy_adapter = __esm({
1657
1727
  "applyActiveDecisionUpdates",
1658
1728
  // getToolCallCount + updatePhaseStatus are ABSENT: they now have edge handlers and
1659
1729
  // are served through the forwarder (getToolCallCount = SUP-2026-026 handler #1).
1660
- "getContributorRole",
1730
+ // getContributorRole is edge-wired and binds identity from the bearer.
1661
1731
  // task-3018 (C356): storeDocBody + getDocBodyUsage are now WIRED — edge case
1662
1732
  // handlers + ALLOWED_METHODS/WRITE_METHODS entries exist, so they forward and
1663
1733
  // hosted callers get body storage. Removed from this list, as task-3017 required.
@@ -1665,9 +1735,6 @@ var init_proxy_adapter = __esm({
1665
1735
  // of the owner-action queue. Six readers were wired C329 (task-2412) but the
1666
1736
  // producer stayed here, so the hosted Owner Action Queue was structurally empty
1667
1737
  // (AD-74 inverted). Now forwards; the edge binds user_id to the bearer ([C]).
1668
- "recordContributorReleasePr",
1669
- "setContributorReleasePrStatus",
1670
- "listContributorReleasePrs",
1671
1738
  "claimReview",
1672
1739
  "getSiblingAds",
1673
1740
  "getSiblingRepoTasks",
@@ -2383,8 +2450,8 @@ Check PAPI_PROJECT_ID in your .mcp.json config. Find your project ID in the PAPI
2383
2450
  getCycleLearningPatterns() {
2384
2451
  return this.invoke("getCycleLearningPatterns", []);
2385
2452
  }
2386
- updateCycleLearningActionRef(learningId, taskDisplayId) {
2387
- return this.invoke("updateCycleLearningActionRef", [learningId, taskDisplayId]);
2453
+ updateCycleLearningActionRef(learningId, taskDisplayId, opts) {
2454
+ return this.invoke("updateCycleLearningActionRef", [learningId, taskDisplayId, opts ?? {}]);
2388
2455
  }
2389
2456
  // --- Strategy Review Drafts ---
2390
2457
  savePendingReviewResponse(cycleNumber, rawResponse) {
@@ -2490,7 +2557,11 @@ Check PAPI_PROJECT_ID in your .mcp.json config. Find your project ID in the PAPI
2490
2557
  */
2491
2558
  async getMeteredUsage() {
2492
2559
  const body = await this.postRoute("metering", {});
2493
- return { tier: body.tier ?? "free", monthlyToolCalls: body.monthlyToolCalls ?? 0 };
2560
+ return {
2561
+ tier: body.tier ?? "free",
2562
+ monthlyToolCalls: body.monthlyToolCalls ?? 0,
2563
+ projectLimitOverride: body.projectLimitOverride ?? null
2564
+ };
2494
2565
  }
2495
2566
  async listUserProjects() {
2496
2567
  const body = await this.postRoute("project-list", {});
@@ -2871,7 +2942,7 @@ Fix the PAPI_PROJECT_ID in your .mcp.json (or unset it and let PAPI resolve the
2871
2942
  Get started in 3 steps:
2872
2943
  1. Sign up at ${dashboardUrl ? `${dashboardUrl}/login` : "your configured PAPI dashboard"}
2873
2944
  2. Complete the onboarding wizard \u2014 it generates your .mcp.json config
2874
- 3. Download the config, place it in your project root, and restart Claude Code
2945
+ 3. Download the config, place it in your project root, and restart your AI client
2875
2946
 
2876
2947
  Already have an account? Make sure PAPI_DATA_API_KEY is set in your .mcp.json env config.`
2877
2948
  );