@papi-ai/server 0.7.45 → 0.7.47
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 +68 -40
- package/dist/index.js +577 -99
- package/dist/prompts.js +10 -0
- package/package.json +3 -2
|
@@ -1163,6 +1163,10 @@ var init_proxy_adapter = __esm({
|
|
|
1163
1163
|
"claimReview",
|
|
1164
1164
|
"getSiblingAds",
|
|
1165
1165
|
"getSiblingRepoTasks"
|
|
1166
|
+
// task-2489 (C320): recordProgressStep is now wired to the edge data-proxy
|
|
1167
|
+
// (case handler + ALLOWED_METHODS/WRITE_METHODS entries), so it forwards for
|
|
1168
|
+
// hosted callers and persists a project-scoped cycle_progress_steps row. Removed
|
|
1169
|
+
// from NO_FORWARD (was the task-2484 pg-only gap) — hosted parity restored.
|
|
1166
1170
|
]);
|
|
1167
1171
|
ProxyPapiAdapter = class _ProxyPapiAdapter {
|
|
1168
1172
|
endpoint;
|
|
@@ -1883,27 +1887,14 @@ import { execSync } from "child_process";
|
|
|
1883
1887
|
import { readFile, writeFile, access } from "fs/promises";
|
|
1884
1888
|
import { randomUUID as randomUUID6 } from "crypto";
|
|
1885
1889
|
import { join } from "path";
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
"Done": [],
|
|
1895
|
-
"Blocked": ["Backlog", "Ready", "In Cycle", "In Progress", "Cancelled"],
|
|
1896
|
-
"Cancelled": [],
|
|
1897
|
-
"Deferred": ["Backlog", "Cancelled"]
|
|
1898
|
-
};
|
|
1899
|
-
var RETIRED_DECISION_OUTCOMES = ["resolved", "abandoned", "superseded"];
|
|
1900
|
-
function isLiveDecision(d) {
|
|
1901
|
-
if (d.superseded === true) return false;
|
|
1902
|
-
if (d.outcome != null && RETIRED_DECISION_OUTCOMES.includes(d.outcome)) return false;
|
|
1903
|
-
return true;
|
|
1904
|
-
}
|
|
1905
|
-
|
|
1906
|
-
// ../adapter-md/dist/index.js
|
|
1890
|
+
import {
|
|
1891
|
+
VALID_TRANSITIONS as _VALID_TRANSITIONS,
|
|
1892
|
+
isValidTransition as _isValidTransition,
|
|
1893
|
+
validateTransition as _validateTransition,
|
|
1894
|
+
isValidStatus as _isValidStatus,
|
|
1895
|
+
isLiveDecision as _isLiveDecision,
|
|
1896
|
+
RETIRED_DECISION_OUTCOMES as _RETIRED_DECISION_OUTCOMES
|
|
1897
|
+
} from "@papi-ai/shared";
|
|
1907
1898
|
import { randomUUID } from "crypto";
|
|
1908
1899
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
1909
1900
|
import yaml from "js-yaml";
|
|
@@ -1912,8 +1903,8 @@ import { randomUUID as randomUUID4 } from "crypto";
|
|
|
1912
1903
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
1913
1904
|
import yaml2 from "js-yaml";
|
|
1914
1905
|
import yaml3 from "js-yaml";
|
|
1915
|
-
var
|
|
1916
|
-
var
|
|
1906
|
+
var VALID_TRANSITIONS = _VALID_TRANSITIONS;
|
|
1907
|
+
var isLiveDecision = _isLiveDecision;
|
|
1917
1908
|
function extractSection(content, heading) {
|
|
1918
1909
|
const headingPattern = new RegExp(`^## ${heading}\\s*$`, "m");
|
|
1919
1910
|
const start = content.search(headingPattern);
|
|
@@ -3106,6 +3097,7 @@ function toCycle(raw) {
|
|
|
3106
3097
|
};
|
|
3107
3098
|
if (raw.end_date) cycle.endDate = raw.end_date;
|
|
3108
3099
|
if (raw.user_id) cycle.userId = raw.user_id;
|
|
3100
|
+
if (raw.dependency_chain) cycle.dependencyChain = raw.dependency_chain;
|
|
3109
3101
|
return cycle;
|
|
3110
3102
|
}
|
|
3111
3103
|
function fromCycle(cycle) {
|
|
@@ -3120,6 +3112,7 @@ function fromCycle(cycle) {
|
|
|
3120
3112
|
};
|
|
3121
3113
|
if (cycle.endDate) raw.end_date = cycle.endDate;
|
|
3122
3114
|
if (cycle.userId) raw.user_id = cycle.userId;
|
|
3115
|
+
if (cycle.dependencyChain) raw.dependency_chain = cycle.dependencyChain;
|
|
3123
3116
|
return raw;
|
|
3124
3117
|
}
|
|
3125
3118
|
function extractYamlBlock2(content) {
|
|
@@ -3164,7 +3157,7 @@ function prependCycle(cycle, content) {
|
|
|
3164
3157
|
const yamlStr = yaml2.dump({ cycles: [raw] }, { lineWidth: 120, quotingType: '"' });
|
|
3165
3158
|
return header + YAML_START2 + "\n" + yamlStr + YAML_END2 + "\n";
|
|
3166
3159
|
}
|
|
3167
|
-
const existing = parseCycles(content);
|
|
3160
|
+
const existing = parseCycles(content).filter((c) => c.number !== cycle.number);
|
|
3168
3161
|
const merged = [cycle, ...existing];
|
|
3169
3162
|
return serializeCycles(merged, content);
|
|
3170
3163
|
}
|
|
@@ -3261,7 +3254,7 @@ var MdFileAdapter = class {
|
|
|
3261
3254
|
if (!content) return [];
|
|
3262
3255
|
const all = parseActiveDecisions(content);
|
|
3263
3256
|
if (options?.includeRetired) return all;
|
|
3264
|
-
return all.filter(
|
|
3257
|
+
return all.filter(isLiveDecision);
|
|
3265
3258
|
}
|
|
3266
3259
|
/** Read cycle log entries (newest first), optionally limited to {@link limit} entries. */
|
|
3267
3260
|
async getCycleLog(limit) {
|
|
@@ -3429,7 +3422,7 @@ var MdFileAdapter = class {
|
|
|
3429
3422
|
}
|
|
3430
3423
|
if (updates.status && updates.status !== tasks[idx].status && !options?.force) {
|
|
3431
3424
|
const from = tasks[idx].status;
|
|
3432
|
-
const allowed =
|
|
3425
|
+
const allowed = VALID_TRANSITIONS[from];
|
|
3433
3426
|
if (!allowed.includes(updates.status)) {
|
|
3434
3427
|
console.warn(`[papi] Warning: invalid status transition "${from}" \u2192 "${updates.status}" for task ${id}. Allowed from "${from}": ${allowed.length > 0 ? allowed.join(", ") : "none"}`);
|
|
3435
3428
|
}
|
|
@@ -4526,31 +4519,66 @@ Check PAPI_PROJECT_ID in your .mcp.json config. Find your project ID in the PAPI
|
|
|
4526
4519
|
}
|
|
4527
4520
|
|
|
4528
4521
|
// src/lib/formatters.ts
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
|
|
4522
|
+
function effortWeight(size) {
|
|
4523
|
+
switch ((size || "").toUpperCase()) {
|
|
4524
|
+
case "XS":
|
|
4525
|
+
return 1;
|
|
4526
|
+
case "S":
|
|
4527
|
+
case "SMALL":
|
|
4528
|
+
return 2;
|
|
4529
|
+
case "M":
|
|
4530
|
+
case "MEDIUM":
|
|
4531
|
+
return 3;
|
|
4532
|
+
case "L":
|
|
4533
|
+
case "LARGE":
|
|
4534
|
+
return 5;
|
|
4535
|
+
case "XL":
|
|
4536
|
+
return 8;
|
|
4537
|
+
default:
|
|
4538
|
+
return 3;
|
|
4539
|
+
}
|
|
4540
|
+
}
|
|
4541
|
+
function computeSnapshotsFromBuildReports(reports, tasks) {
|
|
4542
|
+
const reportsByCycle = /* @__PURE__ */ new Map();
|
|
4533
4543
|
for (const r of reports) {
|
|
4534
|
-
const existing =
|
|
4544
|
+
const existing = reportsByCycle.get(r.cycle) ?? [];
|
|
4535
4545
|
existing.push(r);
|
|
4536
|
-
|
|
4546
|
+
reportsByCycle.set(r.cycle, existing);
|
|
4547
|
+
}
|
|
4548
|
+
const tasksByCycle = /* @__PURE__ */ new Map();
|
|
4549
|
+
for (const t of tasks ?? []) {
|
|
4550
|
+
if (t.cycle == null) continue;
|
|
4551
|
+
const existing = tasksByCycle.get(t.cycle) ?? [];
|
|
4552
|
+
existing.push(t);
|
|
4553
|
+
tasksByCycle.set(t.cycle, existing);
|
|
4537
4554
|
}
|
|
4555
|
+
const cycleNumbers = /* @__PURE__ */ new Set([...reportsByCycle.keys(), ...tasksByCycle.keys()]);
|
|
4556
|
+
if (cycleNumbers.size === 0) return [];
|
|
4538
4557
|
const snapshots = [];
|
|
4539
|
-
for (const
|
|
4540
|
-
const
|
|
4541
|
-
const
|
|
4558
|
+
for (const sn of cycleNumbers) {
|
|
4559
|
+
const cycleReports = reportsByCycle.get(sn) ?? [];
|
|
4560
|
+
const cycleTaskRows = tasksByCycle.get(sn);
|
|
4542
4561
|
const withEffort = cycleReports.filter((r) => r.estimatedEffort && r.actualEffort);
|
|
4543
4562
|
const accurate = withEffort.filter((r) => r.estimatedEffort === r.actualEffort).length;
|
|
4544
4563
|
const matchRate = withEffort.length > 0 ? Math.round(accurate / withEffort.length * 100) : 0;
|
|
4545
|
-
let
|
|
4546
|
-
|
|
4547
|
-
|
|
4564
|
+
let completed;
|
|
4565
|
+
let total;
|
|
4566
|
+
let effortPoints;
|
|
4567
|
+
if (cycleTaskRows && cycleTaskRows.length > 0) {
|
|
4568
|
+
const done = cycleTaskRows.filter((t) => t.status === "Done");
|
|
4569
|
+
completed = done.length;
|
|
4570
|
+
total = cycleTaskRows.length;
|
|
4571
|
+
effortPoints = done.reduce((s, t) => s + effortWeight(t.complexity), 0);
|
|
4572
|
+
} else {
|
|
4573
|
+
completed = cycleReports.filter((r) => r.completed === "Yes").length;
|
|
4574
|
+
total = cycleReports.length;
|
|
4575
|
+
effortPoints = cycleReports.reduce((s, r) => s + effortWeight(r.actualEffort), 0);
|
|
4548
4576
|
}
|
|
4549
4577
|
snapshots.push({
|
|
4550
4578
|
cycle: sn,
|
|
4551
4579
|
date: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4552
|
-
accuracy: [{ cycle: sn, reports:
|
|
4553
|
-
velocity: [{ cycle: sn, completed, partial: 0, failed: total - completed, effortPoints }]
|
|
4580
|
+
accuracy: [{ cycle: sn, reports: cycleReports.length, matchRate, mae: 0, bias: 0 }],
|
|
4581
|
+
velocity: [{ cycle: sn, completed, partial: 0, failed: Math.max(0, total - completed), effortPoints }]
|
|
4554
4582
|
});
|
|
4555
4583
|
}
|
|
4556
4584
|
snapshots.sort((a, b) => a.cycle - b.cycle);
|