@papi-ai/server 0.7.104 → 0.7.105
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/backfill-cycle-metrics.js +20 -4
- package/dist/index.js +143 -13
- package/package.json +1 -1
|
@@ -201,6 +201,7 @@ __export(git_exports, {
|
|
|
201
201
|
ensureLatestDevelop: () => ensureLatestDevelop,
|
|
202
202
|
ensureTagAtHead: () => ensureTagAtHead,
|
|
203
203
|
fetchBaseBranch: () => fetchBaseBranch,
|
|
204
|
+
findCollidingWork: () => findCollidingWork,
|
|
204
205
|
findContributorReleasePullRequests: () => findContributorReleasePullRequests,
|
|
205
206
|
findTaskCommitsOnBase: () => findTaskCommitsOnBase,
|
|
206
207
|
getBaseDivergence: () => getBaseDivergence,
|
|
@@ -1493,6 +1494,23 @@ function getRemoteBranchFiles(cwd, branch, baseBranch) {
|
|
|
1493
1494
|
return [];
|
|
1494
1495
|
}
|
|
1495
1496
|
}
|
|
1497
|
+
function findCollidingWork(cwd, baseBranch, filesLikelyTouched) {
|
|
1498
|
+
if (filesLikelyTouched.length === 0) return null;
|
|
1499
|
+
const prs = listOpenPullRequests(cwd);
|
|
1500
|
+
if (!prs || prs.length === 0) return null;
|
|
1501
|
+
const wanted = new Set(filesLikelyTouched);
|
|
1502
|
+
for (const pr of prs) {
|
|
1503
|
+
const branchFiles = getRemoteBranchFiles(cwd, pr.headRefName, baseBranch);
|
|
1504
|
+
const overlap = branchFiles.filter((f) => wanted.has(f));
|
|
1505
|
+
if (overlap.length > 0) {
|
|
1506
|
+
return {
|
|
1507
|
+
label: `PR #${pr.number} "${pr.title}" (branch \`${pr.headRefName}\`, opened by ${pr.author})`,
|
|
1508
|
+
files: overlap
|
|
1509
|
+
};
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
return null;
|
|
1513
|
+
}
|
|
1496
1514
|
var AUTO_WRITTEN_PATHS, GIT_NETWORK_TIMEOUT_MS, MERGE_RETRY_DELAY_MS, MERGE_MAX_RETRIES, GIT_FETCH_TIMEOUT_MS;
|
|
1497
1515
|
var init_git = __esm({
|
|
1498
1516
|
"src/lib/git.ts"() {
|
|
@@ -1684,7 +1702,6 @@ var init_proxy_adapter = __esm({
|
|
|
1684
1702
|
"getBuildReportsSince",
|
|
1685
1703
|
"getContextHashes",
|
|
1686
1704
|
"getContextUtilisation",
|
|
1687
|
-
"getCostSnapshots",
|
|
1688
1705
|
"getCostSummary",
|
|
1689
1706
|
"getCurrentNorthStar",
|
|
1690
1707
|
"getCycleHealth",
|
|
@@ -2338,9 +2355,8 @@ Check PAPI_PROJECT_ID in your .mcp.json config. Find your project ID in the PAPI
|
|
|
2338
2355
|
getCostSummary(cycleNumber) {
|
|
2339
2356
|
return this.invoke("getCostSummary", [cycleNumber]);
|
|
2340
2357
|
}
|
|
2341
|
-
getCostSnapshots
|
|
2342
|
-
|
|
2343
|
-
}
|
|
2358
|
+
// task-3332: getCostSnapshots retired — see the removal note on CostSnapshot
|
|
2359
|
+
// in packages/shared/src/entities.ts.
|
|
2344
2360
|
appendCycleMetrics(snapshot) {
|
|
2345
2361
|
return this.invoke("appendCycleMetrics", [snapshot]);
|
|
2346
2362
|
}
|
package/dist/index.js
CHANGED
|
@@ -971,6 +971,7 @@ __export(git_exports, {
|
|
|
971
971
|
ensureLatestDevelop: () => ensureLatestDevelop,
|
|
972
972
|
ensureTagAtHead: () => ensureTagAtHead,
|
|
973
973
|
fetchBaseBranch: () => fetchBaseBranch,
|
|
974
|
+
findCollidingWork: () => findCollidingWork,
|
|
974
975
|
findContributorReleasePullRequests: () => findContributorReleasePullRequests,
|
|
975
976
|
findTaskCommitsOnBase: () => findTaskCommitsOnBase,
|
|
976
977
|
getBaseDivergence: () => getBaseDivergence,
|
|
@@ -2263,6 +2264,23 @@ function getRemoteBranchFiles(cwd, branch, baseBranch) {
|
|
|
2263
2264
|
return [];
|
|
2264
2265
|
}
|
|
2265
2266
|
}
|
|
2267
|
+
function findCollidingWork(cwd, baseBranch, filesLikelyTouched) {
|
|
2268
|
+
if (filesLikelyTouched.length === 0) return null;
|
|
2269
|
+
const prs = listOpenPullRequests(cwd);
|
|
2270
|
+
if (!prs || prs.length === 0) return null;
|
|
2271
|
+
const wanted = new Set(filesLikelyTouched);
|
|
2272
|
+
for (const pr of prs) {
|
|
2273
|
+
const branchFiles = getRemoteBranchFiles(cwd, pr.headRefName, baseBranch);
|
|
2274
|
+
const overlap = branchFiles.filter((f) => wanted.has(f));
|
|
2275
|
+
if (overlap.length > 0) {
|
|
2276
|
+
return {
|
|
2277
|
+
label: `PR #${pr.number} "${pr.title}" (branch \`${pr.headRefName}\`, opened by ${pr.author})`,
|
|
2278
|
+
files: overlap
|
|
2279
|
+
};
|
|
2280
|
+
}
|
|
2281
|
+
}
|
|
2282
|
+
return null;
|
|
2283
|
+
}
|
|
2266
2284
|
var AUTO_WRITTEN_PATHS, GIT_NETWORK_TIMEOUT_MS, MERGE_RETRY_DELAY_MS, MERGE_MAX_RETRIES, GIT_FETCH_TIMEOUT_MS;
|
|
2267
2285
|
var init_git = __esm({
|
|
2268
2286
|
"src/lib/git.ts"() {
|
|
@@ -2520,7 +2538,6 @@ var init_proxy_adapter = __esm({
|
|
|
2520
2538
|
"getBuildReportsSince",
|
|
2521
2539
|
"getContextHashes",
|
|
2522
2540
|
"getContextUtilisation",
|
|
2523
|
-
"getCostSnapshots",
|
|
2524
2541
|
"getCostSummary",
|
|
2525
2542
|
"getCurrentNorthStar",
|
|
2526
2543
|
"getCycleHealth",
|
|
@@ -3174,9 +3191,8 @@ Check PAPI_PROJECT_ID in your .mcp.json config. Find your project ID in the PAPI
|
|
|
3174
3191
|
getCostSummary(cycleNumber) {
|
|
3175
3192
|
return this.invoke("getCostSummary", [cycleNumber]);
|
|
3176
3193
|
}
|
|
3177
|
-
getCostSnapshots
|
|
3178
|
-
|
|
3179
|
-
}
|
|
3194
|
+
// task-3332: getCostSnapshots retired — see the removal note on CostSnapshot
|
|
3195
|
+
// in packages/shared/src/entities.ts.
|
|
3180
3196
|
appendCycleMetrics(snapshot) {
|
|
3181
3197
|
return this.invoke("appendCycleMetrics", [snapshot]);
|
|
3182
3198
|
}
|
|
@@ -27762,7 +27778,7 @@ function resolveAdHocCycle(cycle, latest, latestComplete) {
|
|
|
27762
27778
|
if (cycle === "current") return latest;
|
|
27763
27779
|
return latestComplete ? latest + 1 : latest;
|
|
27764
27780
|
}
|
|
27765
|
-
async function recordAdHoc(adapter2, input) {
|
|
27781
|
+
async function recordAdHoc(adapter2, config2, input) {
|
|
27766
27782
|
const [health, phases] = await Promise.all([
|
|
27767
27783
|
adapter2.getCycleHealth(),
|
|
27768
27784
|
adapter2.readPhases()
|
|
@@ -27784,9 +27800,16 @@ async function recordAdHoc(adapter2, input) {
|
|
|
27784
27800
|
if (!existing) {
|
|
27785
27801
|
throw new Error(`Task "${input.taskId}" not found on the board. Check the task ID and try again.`);
|
|
27786
27802
|
}
|
|
27787
|
-
if (
|
|
27803
|
+
if (existing.assigneeId) {
|
|
27804
|
+
const gate = await resolveOwnerGate(adapter2, config2);
|
|
27805
|
+
if (gate.enforced && (!gate.callerUserId || gate.callerUserId !== existing.assigneeId)) {
|
|
27806
|
+
throw new Error(
|
|
27807
|
+
`Task "${input.taskId}" (${existing.title}) is claimed by another member \u2014 ad-hoc work cannot be recorded against it. Have the claimer record it, or run \`task_unclaim\` to release it first.`
|
|
27808
|
+
);
|
|
27809
|
+
}
|
|
27810
|
+
} else {
|
|
27788
27811
|
warnings.push(
|
|
27789
|
-
`\u2139\uFE0F ${input.taskId} has no assignee \u2014 recording ad-hoc work against an unclaimed pool task. If someone else might be building it too, check for an open PR/branch on the same files before merging.`
|
|
27812
|
+
`\u2139\uFE0F ${input.taskId} has no assignee \u2014 recording ad-hoc work against an unclaimed pool task. ` + (input.collidingWorkNote ?? `If someone else might be building it too, check for an open PR/branch on the same files before merging.`)
|
|
27790
27813
|
);
|
|
27791
27814
|
}
|
|
27792
27815
|
const updatePayload = {
|
|
@@ -28043,7 +28066,22 @@ async function handleAdHoc(adapter2, config2, args) {
|
|
|
28043
28066
|
const gitUsable = !overrideNote && isGitAvailable() && isGitRepo(config2.projectRoot);
|
|
28044
28067
|
const currentBranch = gitUsable ? getCurrentBranch(config2.projectRoot) : null;
|
|
28045
28068
|
const baseBranch = gitUsable ? resolveBaseBranch(config2.projectRoot, config2.baseBranch) : null;
|
|
28046
|
-
|
|
28069
|
+
let collidingWorkNote;
|
|
28070
|
+
if (taskId && gitUsable && baseBranch) {
|
|
28071
|
+
try {
|
|
28072
|
+
const existingTask = await target.getTask(taskId);
|
|
28073
|
+
const filesLikelyTouched = existingTask?.buildHandoff?.filesLikelyTouched ?? [];
|
|
28074
|
+
if (existingTask && !existingTask.assigneeId && filesLikelyTouched.length > 0) {
|
|
28075
|
+
const collision = findCollidingWork(config2.projectRoot, baseBranch, filesLikelyTouched);
|
|
28076
|
+
if (collision) {
|
|
28077
|
+
const fileList = collision.files.slice(0, 3).join(", ") + (collision.files.length > 3 ? ", \u2026" : "");
|
|
28078
|
+
collidingWorkNote = `${collision.label} already touches ${collision.files.length === 1 ? "the same file" : `${collision.files.length} of the same files`} (${fileList}) \u2014 check it before merging.`;
|
|
28079
|
+
}
|
|
28080
|
+
}
|
|
28081
|
+
} catch {
|
|
28082
|
+
}
|
|
28083
|
+
}
|
|
28084
|
+
const result = await recordAdHoc(target, config2, {
|
|
28047
28085
|
title: title || "",
|
|
28048
28086
|
taskId,
|
|
28049
28087
|
notes: rawNotes,
|
|
@@ -28058,7 +28096,8 @@ async function handleAdHoc(adapter2, config2, args) {
|
|
|
28058
28096
|
stage: stageArg,
|
|
28059
28097
|
hold: holdArg,
|
|
28060
28098
|
currentBranch,
|
|
28061
|
-
baseBranch
|
|
28099
|
+
baseBranch,
|
|
28100
|
+
collidingWorkNote
|
|
28062
28101
|
});
|
|
28063
28102
|
if (!holdArg && gitUsable) {
|
|
28064
28103
|
try {
|
|
@@ -29090,6 +29129,27 @@ var reviewSubmitTool = {
|
|
|
29090
29129
|
}
|
|
29091
29130
|
},
|
|
29092
29131
|
required: ["verdict", "summary", "findings"]
|
|
29132
|
+
},
|
|
29133
|
+
proposal: {
|
|
29134
|
+
type: "object",
|
|
29135
|
+
description: 'task-3388, OPTIONAL (build-acceptance + verdict:"accept" only): propose a Decision or a Convention the build or the review itself settled. Same mechanism as build_execute\u2019s `proposal` (task-3273) \u2014 PAPI never mints one for you. A proposal that passes all four admission tests is QUEUED for the owner behind a decision gate, and nothing is written as an Active Decision. YOU apply the four tests (they are stated in the planning prompts); the server routes on your answers and makes no judgement about the content. Fails "arguable today" only and it is recorded as a Convention instead, riding every future build. Fails "constrains future work" and it is returned to you with the reason, unrecorded.',
|
|
29136
|
+
properties: {
|
|
29137
|
+
title: { type: "string", description: "One line stating the stance or rule." },
|
|
29138
|
+
body: { type: "string", description: "What was decided or settled, and why." },
|
|
29139
|
+
module: { type: "string", description: "Optional module scope. Only used when this lands as a Convention." },
|
|
29140
|
+
tests: {
|
|
29141
|
+
type: "object",
|
|
29142
|
+
description: "The four admission tests, each answered explicitly. An omitted test is NOT a failed test \u2014 the proposal is refused rather than routed.",
|
|
29143
|
+
properties: {
|
|
29144
|
+
alternativesWereReal: { type: "boolean", description: "(a) Something else could genuinely have been chosen." },
|
|
29145
|
+
constrainsFutureWork: { type: "boolean", description: "(b) It changes what a task nobody has written yet will do." },
|
|
29146
|
+
arguableToday: { type: "boolean", description: "(c) A competent person could argue the other side right now." },
|
|
29147
|
+
reversalCostsMore: { type: "boolean", description: "(d) Reversing it costs more than making it did." }
|
|
29148
|
+
},
|
|
29149
|
+
required: ["alternativesWereReal", "constrainsFutureWork", "arguableToday", "reversalCostsMore"]
|
|
29150
|
+
}
|
|
29151
|
+
},
|
|
29152
|
+
required: ["title", "body", "tests"]
|
|
29093
29153
|
}
|
|
29094
29154
|
},
|
|
29095
29155
|
required: ["task_id", "stage", "verdict", "comments"],
|
|
@@ -29705,6 +29765,30 @@ Next: address the feedback, then run \`build_execute ${taskId}\` to resubmit.`;
|
|
|
29705
29765
|
}
|
|
29706
29766
|
} catch {
|
|
29707
29767
|
}
|
|
29768
|
+
let proposalNote = "";
|
|
29769
|
+
if (args.proposal !== void 0) {
|
|
29770
|
+
if (!(stage === "build-acceptance" && verdict === "accept")) {
|
|
29771
|
+
proposalNote = "\n\n---\n\n**Proposal not recorded.** `proposal` is only accepted on a build-acceptance `accept` \u2014 nothing has settled on a handoff-review or a non-accept verdict.\n\nThe review itself is unaffected \u2014 only the proposal was skipped.";
|
|
29772
|
+
} else {
|
|
29773
|
+
const validated = validateProposal(args.proposal);
|
|
29774
|
+
if ("error" in validated) {
|
|
29775
|
+
proposalNote = `
|
|
29776
|
+
|
|
29777
|
+
---
|
|
29778
|
+
|
|
29779
|
+
**Proposal not recorded.** ${validated.error}
|
|
29780
|
+
|
|
29781
|
+
The review itself is unaffected \u2014 only the proposal failed.`;
|
|
29782
|
+
} else {
|
|
29783
|
+
const routing = routeProposal(validated.proposal);
|
|
29784
|
+
const applied = await applyProposal(adapter2, routing, validated.proposal, {
|
|
29785
|
+
cycleNumber: result.currentCycle,
|
|
29786
|
+
sourceTaskId: result.taskId
|
|
29787
|
+
});
|
|
29788
|
+
proposalNote = formatProposalOutcome(routing, validated.proposal, applied);
|
|
29789
|
+
}
|
|
29790
|
+
}
|
|
29791
|
+
}
|
|
29708
29792
|
tracker.mark("format-response");
|
|
29709
29793
|
return textResponse(
|
|
29710
29794
|
`**${result.stageLabel}** recorded for ${result.taskId}.
|
|
@@ -29712,7 +29796,7 @@ Next: address the feedback, then run \`build_execute ${taskId}\` to resubmit.`;
|
|
|
29712
29796
|
- **Verdict:** ${result.verdict}
|
|
29713
29797
|
- **Comments:** ${trimForEcho(result.comments)}
|
|
29714
29798
|
|
|
29715
|
-
${statusNote}${capabilityReviewSkippedNote}${autoReviewNote}${securityNote}${adConflictNote}${unblockNote}${docClosureNote}${regenNote}${mergeNote}${overlapNote}${batchSummaryNote}${autoReleaseNote}${nextStepNote}${phaseNote}`
|
|
29799
|
+
${statusNote}${capabilityReviewSkippedNote}${autoReviewNote}${securityNote}${adConflictNote}${unblockNote}${docClosureNote}${regenNote}${mergeNote}${overlapNote}${batchSummaryNote}${autoReleaseNote}${nextStepNote}${phaseNote}${proposalNote}`
|
|
29716
29800
|
);
|
|
29717
29801
|
} catch (err) {
|
|
29718
29802
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -30746,6 +30830,41 @@ function formatUnblockSection(candidates) {
|
|
|
30746
30830
|
return lines.join("\n");
|
|
30747
30831
|
}
|
|
30748
30832
|
|
|
30833
|
+
// src/lib/decision-drafts.ts
|
|
30834
|
+
async function findPendingDecisionDrafts(adapter2) {
|
|
30835
|
+
let blockedProbe;
|
|
30836
|
+
try {
|
|
30837
|
+
blockedProbe = await adapter2.queryBoard({ status: ["Blocked"], compact: true });
|
|
30838
|
+
} catch {
|
|
30839
|
+
return [];
|
|
30840
|
+
}
|
|
30841
|
+
if (blockedProbe.length === 0) return [];
|
|
30842
|
+
const drafts = [];
|
|
30843
|
+
for (const task of blockedProbe) {
|
|
30844
|
+
const blocker = task.blocker;
|
|
30845
|
+
if (!blocker || blocker.type !== "decision-gate" || blocker.ref !== PROPOSED_DECISION_REF) continue;
|
|
30846
|
+
const evidence = (task.notes ?? "").split("\n")[0]?.trim() ?? "";
|
|
30847
|
+
drafts.push({
|
|
30848
|
+
taskId: task.displayId ?? task.id,
|
|
30849
|
+
taskTitle: task.title,
|
|
30850
|
+
evidence
|
|
30851
|
+
});
|
|
30852
|
+
}
|
|
30853
|
+
return drafts;
|
|
30854
|
+
}
|
|
30855
|
+
function formatPendingDecisionDrafts(drafts) {
|
|
30856
|
+
if (drafts.length === 0) return "";
|
|
30857
|
+
const lines = ["## Decisions Awaiting Your Call"];
|
|
30858
|
+
lines.push(
|
|
30859
|
+
`${drafts.length} decision${drafts.length === 1 ? "" : "s"} proposed during a build, waiting on you \u2014 mint with \`strategy_change\` to make it a real Active Decision, or \`board_edit <task> status:Cancelled\` to dismiss it. Neither is automatic.`
|
|
30860
|
+
);
|
|
30861
|
+
lines.push("");
|
|
30862
|
+
for (const d of drafts) {
|
|
30863
|
+
lines.push(`- **${formatRef(d.taskId, d.taskTitle)}**${d.evidence ? ` \u2014 ${d.evidence}` : ""}`);
|
|
30864
|
+
}
|
|
30865
|
+
return lines.join("\n");
|
|
30866
|
+
}
|
|
30867
|
+
|
|
30749
30868
|
// src/lib/deferred-gate.ts
|
|
30750
30869
|
var GATE_PHRASES = [
|
|
30751
30870
|
"depends on",
|
|
@@ -32288,7 +32407,8 @@ async function handleOrient(rawAdapter, config2, args = {}, clientName, serverVe
|
|
|
32288
32407
|
}
|
|
32289
32408
|
let unrecordedNote2 = "";
|
|
32290
32409
|
try {
|
|
32291
|
-
const
|
|
32410
|
+
const { compareRef } = getBaseDivergence(config2.projectRoot, config2.baseBranch, { timeoutMs: ORIGIN_FETCH_TIMEOUT_MS });
|
|
32411
|
+
const unrecorded = detectUnrecordedCommits(config2.projectRoot, compareRef);
|
|
32292
32412
|
if (unrecorded.length > 0) {
|
|
32293
32413
|
const doneTasks = await adapter2.queryBoard({ status: ["Done"] });
|
|
32294
32414
|
const adHocDoneTasks = doneTasks.filter((t) => t.cycle == null);
|
|
@@ -32417,8 +32537,14 @@ ${versionDrift}` : "";
|
|
|
32417
32537
|
}
|
|
32418
32538
|
tracker.mark("parallel-tail");
|
|
32419
32539
|
const sharedContributorsPromise = adapterSupports(adapter2, "listContributors") ? adapter2.listContributors().catch(() => []) : Promise.resolve([]);
|
|
32420
|
-
const [unblockCandidates, subAgents, teamSummaryLine, releaseHistoryLine, cohortVisibilityLine, carryForwardRefs] = await Promise.all([
|
|
32540
|
+
const [unblockCandidates, pendingDecisionDrafts, subAgents, teamSummaryLine, releaseHistoryLine, cohortVisibilityLine, carryForwardRefs] = await Promise.all([
|
|
32421
32541
|
tracked("unblock-candidates", () => findUnblockCandidates(adapter2, currentCycle2))().catch(() => []),
|
|
32542
|
+
// task-3388: pending decision-proposal drafts (build_execute/review_submit's
|
|
32543
|
+
// `proposal` param, task-3273/3388) — mandatory reader, deliberately
|
|
32544
|
+
// uncapped and separate from the housekeeping-suggestion unblock list above
|
|
32545
|
+
// (see lib/decision-drafts.ts for why). Runs on every orient call, not
|
|
32546
|
+
// gated behind deep_housekeeping — same posture as unblock-candidates.
|
|
32547
|
+
tracked("pending-decision-drafts", () => findPendingDecisionDrafts(adapter2))().catch(() => []),
|
|
32422
32548
|
// task-1866: discover project sub-agents for the orient surface (read-only, never throws).
|
|
32423
32549
|
listAgents(config2.projectRoot),
|
|
32424
32550
|
// task-2071 (MU-3) + task-2072 (MU-5): team summary + release-history — both
|
|
@@ -32437,6 +32563,10 @@ ${versionDrift}` : "";
|
|
|
32437
32563
|
const unblockNote = unblockSection ? `
|
|
32438
32564
|
|
|
32439
32565
|
${unblockSection}` : "";
|
|
32566
|
+
const decisionDraftsSection = formatPendingDecisionDrafts(pendingDecisionDrafts);
|
|
32567
|
+
const decisionDraftsNote = decisionDraftsSection ? `
|
|
32568
|
+
|
|
32569
|
+
${decisionDraftsSection}` : "";
|
|
32440
32570
|
const teamSummary = [teamSummaryLine, releaseHistoryLine, cohortVisibilityLine].filter(Boolean).join("\n") || void 0;
|
|
32441
32571
|
let deferredGateNote = "";
|
|
32442
32572
|
if (deepHousekeeping) {
|
|
@@ -32472,7 +32602,7 @@ ${formatRuntimeIdentity(getRuntimeIdentity(config2, serverVersion))}`;
|
|
|
32472
32602
|
let effStaleSkillsNote = staleSkillsNote;
|
|
32473
32603
|
let effResearchSignalsNote = researchSignalsNote;
|
|
32474
32604
|
const droppedNotes = [];
|
|
32475
|
-
const assembleOrientOutput = () => projectOverrideLine + projectBannerNote + formatOrientSummary(healthResult, buildInfo, hierarchy, latestTag, config2.projectRoot, environment, subAgents, projectName, teamSummary, clientName, carryForwardRefs) + runtimeIdentityNote + unblockNote + deferredGateNote + feedbackResolvedNote + alertsNote + ttfvNote + reconciliationNote + mergedInProgressNote + unrecordedNote + unregisteredDocsNote + effStaleSkillsNote + effResearchSignalsNote + recsNote + pendingReviewNote + patternsNote + unactionedIssuesNote + skillProposalsNote + sessionGuidanceNote + effOnboardingCoachingNote + versionNote + enrichmentNote + deliveryShapeNote + preBuildCheckNote + effDeepHint + enrichmentFilesSection;
|
|
32605
|
+
const assembleOrientOutput = () => projectOverrideLine + projectBannerNote + formatOrientSummary(healthResult, buildInfo, hierarchy, latestTag, config2.projectRoot, environment, subAgents, projectName, teamSummary, clientName, carryForwardRefs) + runtimeIdentityNote + unblockNote + decisionDraftsNote + deferredGateNote + feedbackResolvedNote + alertsNote + ttfvNote + reconciliationNote + mergedInProgressNote + unrecordedNote + unregisteredDocsNote + effStaleSkillsNote + effResearchSignalsNote + recsNote + pendingReviewNote + patternsNote + unactionedIssuesNote + skillProposalsNote + sessionGuidanceNote + effOnboardingCoachingNote + versionNote + enrichmentNote + deliveryShapeNote + preBuildCheckNote + effDeepHint + enrichmentFilesSection;
|
|
32476
32606
|
const orientBudgetSoft = Number(process.env.PAPI_ORIENT_CONTEXT_BUDGET) || 6e4;
|
|
32477
32607
|
let assembled = assembleOrientOutput();
|
|
32478
32608
|
if (Buffer.byteLength(assembled, "utf-8") > orientBudgetSoft && effDeepHint) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@papi-ai/server",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.105",
|
|
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",
|