syntaur 0.49.0 → 0.51.0
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/.claude-plugin/plugin.json +1 -1
- package/dashboard/dist/assets/{_basePickBy-D_1PqV49.js → _basePickBy-iqEGomW8.js} +1 -1
- package/dashboard/dist/assets/{_baseUniq-Go3lJYWk.js → _baseUniq--Qg0UGRL.js} +1 -1
- package/dashboard/dist/assets/{arc-CPkf0K8o.js → arc-DARwlKiU.js} +1 -1
- package/dashboard/dist/assets/{architectureDiagram-2XIMDMQ5-D-YQc-ni.js → architectureDiagram-2XIMDMQ5-oWU1lL2y.js} +1 -1
- package/dashboard/dist/assets/{blockDiagram-WCTKOSBZ-BYKjgbgS.js → blockDiagram-WCTKOSBZ-DMuCwZLv.js} +1 -1
- package/dashboard/dist/assets/{c4Diagram-IC4MRINW-DL0q4c_7.js → c4Diagram-IC4MRINW-Axpp-L4P.js} +1 -1
- package/dashboard/dist/assets/channel-DJkgIua7.js +1 -0
- package/dashboard/dist/assets/{chunk-4BX2VUAB-Dz3hphvh.js → chunk-4BX2VUAB-BE-Yhqdt.js} +1 -1
- package/dashboard/dist/assets/{chunk-55IACEB6-KkMi7-rO.js → chunk-55IACEB6-DacZdH_M.js} +1 -1
- package/dashboard/dist/assets/{chunk-FMBD7UC4-C6i7PgE-.js → chunk-FMBD7UC4-vAEg5Z3N.js} +1 -1
- package/dashboard/dist/assets/{chunk-JSJVCQXG-D9nWD3SH.js → chunk-JSJVCQXG-CTukijKn.js} +1 -1
- package/dashboard/dist/assets/{chunk-KX2RTZJC-C-pz_QfY.js → chunk-KX2RTZJC-C-lU6Wil.js} +1 -1
- package/dashboard/dist/assets/{chunk-NQ4KR5QH-m21dA_AB.js → chunk-NQ4KR5QH-m-jZxhEZ.js} +1 -1
- package/dashboard/dist/assets/{chunk-QZHKN3VN-BTYD7vUi.js → chunk-QZHKN3VN-VA8PtmgY.js} +1 -1
- package/dashboard/dist/assets/{chunk-WL4C6EOR-D_92eLJ7.js → chunk-WL4C6EOR-BhM9cEr9.js} +1 -1
- package/dashboard/dist/assets/classDiagram-VBA2DB6C-BQpVKOOw.js +1 -0
- package/dashboard/dist/assets/classDiagram-v2-RAHNMMFH-BQpVKOOw.js +1 -0
- package/dashboard/dist/assets/clone-Cyb0u6Fm.js +1 -0
- package/dashboard/dist/assets/{cose-bilkent-S5V4N54A-xG37nIJ5.js → cose-bilkent-S5V4N54A-DBGtEkKf.js} +1 -1
- package/dashboard/dist/assets/{dagre-KLK3FWXG-BmMnqFf5.js → dagre-KLK3FWXG-BIU8RfcY.js} +1 -1
- package/dashboard/dist/assets/{diagram-E7M64L7V-NKwCHorn.js → diagram-E7M64L7V-C1OD19qw.js} +1 -1
- package/dashboard/dist/assets/{diagram-IFDJBPK2-RFbM55z9.js → diagram-IFDJBPK2-B-VWSLa6.js} +1 -1
- package/dashboard/dist/assets/{diagram-P4PSJMXO-DFATQN63.js → diagram-P4PSJMXO-gpFwgRk6.js} +1 -1
- package/dashboard/dist/assets/{erDiagram-INFDFZHY-CnkbUfYo.js → erDiagram-INFDFZHY-MxL4ZzOD.js} +1 -1
- package/dashboard/dist/assets/{flowDiagram-PKNHOUZH-C2bCpv_b.js → flowDiagram-PKNHOUZH-B0BqXx8A.js} +1 -1
- package/dashboard/dist/assets/{ganttDiagram-A5KZAMGK-Cyz3i9ox.js → ganttDiagram-A5KZAMGK-CZSBVo4l.js} +1 -1
- package/dashboard/dist/assets/{gitGraphDiagram-K3NZZRJ6-DNSJOJPu.js → gitGraphDiagram-K3NZZRJ6-CfXBKQ-d.js} +1 -1
- package/dashboard/dist/assets/{graph-B0uvMYEt.js → graph-IrjCiOoy.js} +1 -1
- package/dashboard/dist/assets/index-BHyNXpJx.js +577 -0
- package/dashboard/dist/assets/index-KhylT_54.css +1 -0
- package/dashboard/dist/assets/{infoDiagram-LFFYTUFH-CIAGOhnc.js → infoDiagram-LFFYTUFH-Rf9ZeCX3.js} +1 -1
- package/dashboard/dist/assets/{ishikawaDiagram-PHBUUO56-Cz1e1z95.js → ishikawaDiagram-PHBUUO56-RAQWTALS.js} +1 -1
- package/dashboard/dist/assets/{journeyDiagram-4ABVD52K-DQpnaGS3.js → journeyDiagram-4ABVD52K-ZcEWsM-p.js} +1 -1
- package/dashboard/dist/assets/{kanban-definition-K7BYSVSG-ctedqNYC.js → kanban-definition-K7BYSVSG-B-GmGguF.js} +1 -1
- package/dashboard/dist/assets/{layout-DB-MZUE7.js → layout-CGl1QE2H.js} +1 -1
- package/dashboard/dist/assets/{linear-ChyfHemL.js → linear-C8T_EWa_.js} +1 -1
- package/dashboard/dist/assets/{mermaid.core-B7D9g8Z0.js → mermaid.core-_rgvEzla.js} +4 -4
- package/dashboard/dist/assets/{mindmap-definition-YRQLILUH-BBwO3Cx_.js → mindmap-definition-YRQLILUH-D9eiyPrJ.js} +1 -1
- package/dashboard/dist/assets/{pieDiagram-SKSYHLDU-D5cgYxWS.js → pieDiagram-SKSYHLDU-DuAS5_1b.js} +1 -1
- package/dashboard/dist/assets/{quadrantDiagram-337W2JSQ-D1PRaNvQ.js → quadrantDiagram-337W2JSQ-Bs9cFwnM.js} +1 -1
- package/dashboard/dist/assets/{requirementDiagram-Z7DCOOCP-DSPKmecF.js → requirementDiagram-Z7DCOOCP-P8h8bKqs.js} +1 -1
- package/dashboard/dist/assets/{sankeyDiagram-WA2Y5GQK-qoBrVPPJ.js → sankeyDiagram-WA2Y5GQK-jvYtbQv9.js} +1 -1
- package/dashboard/dist/assets/{sequenceDiagram-2WXFIKYE-COHgbUzd.js → sequenceDiagram-2WXFIKYE-dfHtIxLr.js} +1 -1
- package/dashboard/dist/assets/{stateDiagram-RAJIS63D-D7o2ec5P.js → stateDiagram-RAJIS63D-BVKA9rS_.js} +1 -1
- package/dashboard/dist/assets/stateDiagram-v2-FVOUBMTO-B1fHHK2b.js +1 -0
- package/dashboard/dist/assets/{timeline-definition-YZTLITO2-0_qvF5FF.js → timeline-definition-YZTLITO2-Cm1H8Att.js} +1 -1
- package/dashboard/dist/assets/{treemap-KZPCXAKY-DrWRWtnJ.js → treemap-KZPCXAKY-BRzwg_ce.js} +1 -1
- package/dashboard/dist/assets/{vennDiagram-LZ73GAT5-Chnf9HfQ.js → vennDiagram-LZ73GAT5-BJ4UoDVK.js} +1 -1
- package/dashboard/dist/assets/{xychartDiagram-JWTSCODW-DZaMVdVS.js → xychartDiagram-JWTSCODW-TyeURVy0.js} +1 -1
- package/dashboard/dist/index.html +2 -2
- package/dist/dashboard/server.js +300 -171
- package/dist/dashboard/server.js.map +1 -1
- package/dist/index.js +300 -171
- package/dist/index.js.map +1 -1
- package/dist/launch/index.d.ts +35 -21
- package/dist/launch/index.js +151 -85
- package/dist/launch/index.js.map +1 -1
- package/package.json +1 -1
- package/platforms/claude-code/.claude-plugin/plugin.json +1 -1
- package/platforms/claude-code/skills/manage-statuses/SKILL.md +17 -0
- package/platforms/codex/.codex-plugin/plugin.json +1 -1
- package/platforms/codex/skills/manage-statuses/SKILL.md +17 -0
- package/platforms/hermes/plugins/syntaur/__pycache__/__init__.cpython-312.pyc +0 -0
- package/platforms/hermes/plugins/syntaur/__pycache__/boundary.cpython-312.pyc +0 -0
- package/skills/manage-statuses/SKILL.md +17 -0
- package/dashboard/dist/assets/channel-BogPsJQf.js +0 -1
- package/dashboard/dist/assets/classDiagram-VBA2DB6C-LFy25hGC.js +0 -1
- package/dashboard/dist/assets/classDiagram-v2-RAHNMMFH-LFy25hGC.js +0 -1
- package/dashboard/dist/assets/clone-B2jJrmVo.js +0 -1
- package/dashboard/dist/assets/index-J9J1LmFz.js +0 -567
- package/dashboard/dist/assets/index-hXP7kHLF.css +0 -1
- package/dashboard/dist/assets/stateDiagram-v2-FVOUBMTO-Bn85KIR5.js +0 -1
package/dist/index.js
CHANGED
|
@@ -2411,6 +2411,131 @@ var init_slug = __esm({
|
|
|
2411
2411
|
}
|
|
2412
2412
|
});
|
|
2413
2413
|
|
|
2414
|
+
// src/utils/derive-config.ts
|
|
2415
|
+
function validateDeriveShape(value) {
|
|
2416
|
+
const problems = [];
|
|
2417
|
+
if (!value || typeof value !== "object") {
|
|
2418
|
+
return ["derive must be an object"];
|
|
2419
|
+
}
|
|
2420
|
+
const d = value;
|
|
2421
|
+
if (!Array.isArray(d.phaseLadder)) {
|
|
2422
|
+
problems.push("derive.phaseLadder must be an array");
|
|
2423
|
+
} else {
|
|
2424
|
+
d.phaseLadder.forEach((rung, i) => {
|
|
2425
|
+
if (!rung || typeof rung !== "object") {
|
|
2426
|
+
problems.push(`derive.phaseLadder[${i}] must be an object`);
|
|
2427
|
+
return;
|
|
2428
|
+
}
|
|
2429
|
+
const r = rung;
|
|
2430
|
+
if (typeof r.phase !== "string") problems.push(`derive.phaseLadder[${i}].phase must be a string`);
|
|
2431
|
+
if (typeof r.when !== "string") problems.push(`derive.phaseLadder[${i}].when must be a string`);
|
|
2432
|
+
if (r.next !== void 0 && typeof r.next !== "string") {
|
|
2433
|
+
problems.push(`derive.phaseLadder[${i}].next must be a string when present`);
|
|
2434
|
+
}
|
|
2435
|
+
});
|
|
2436
|
+
}
|
|
2437
|
+
if (!Array.isArray(d.disposition)) {
|
|
2438
|
+
problems.push("derive.disposition must be an array");
|
|
2439
|
+
} else {
|
|
2440
|
+
d.disposition.forEach((rule, i) => {
|
|
2441
|
+
if (!rule || typeof rule !== "object") {
|
|
2442
|
+
problems.push(`derive.disposition[${i}] must be an object`);
|
|
2443
|
+
return;
|
|
2444
|
+
}
|
|
2445
|
+
const r = rule;
|
|
2446
|
+
if (!(r.when === null || typeof r.when === "string")) {
|
|
2447
|
+
problems.push(`derive.disposition[${i}].when must be a string or null`);
|
|
2448
|
+
}
|
|
2449
|
+
if (typeof r.is !== "string") problems.push(`derive.disposition[${i}].is must be a string`);
|
|
2450
|
+
});
|
|
2451
|
+
}
|
|
2452
|
+
const headline = d.headline;
|
|
2453
|
+
if (!headline || typeof headline !== "object") {
|
|
2454
|
+
problems.push("derive.headline must be an object");
|
|
2455
|
+
} else {
|
|
2456
|
+
if (typeof headline.parked !== "string") problems.push("derive.headline.parked must be a string");
|
|
2457
|
+
if (typeof headline.blocked !== "string") problems.push("derive.headline.blocked must be a string");
|
|
2458
|
+
}
|
|
2459
|
+
return problems;
|
|
2460
|
+
}
|
|
2461
|
+
function validateDeriveConfig(derive, statusConfig, validateWhen = () => null) {
|
|
2462
|
+
const problems = [];
|
|
2463
|
+
const ids = new Set(statusConfig.statuses.map((s) => s.id));
|
|
2464
|
+
if (derive.phaseLadder.length === 0) {
|
|
2465
|
+
problems.push("phaseLadder must have at least one rung");
|
|
2466
|
+
}
|
|
2467
|
+
for (const rung of derive.phaseLadder) {
|
|
2468
|
+
if (!ids.has(rung.phase)) {
|
|
2469
|
+
problems.push(`phaseLadder rung "${rung.phase}" is not a defined status id`);
|
|
2470
|
+
}
|
|
2471
|
+
const err2 = rung.when === "*" ? null : validateWhen(rung.when);
|
|
2472
|
+
if (err2) problems.push(`phaseLadder rung "${rung.phase}": invalid condition \u2014 ${err2}`);
|
|
2473
|
+
}
|
|
2474
|
+
const VALID_DISPOSITIONS = /* @__PURE__ */ new Set(["active", "blocked", "parked"]);
|
|
2475
|
+
for (const rule of derive.disposition) {
|
|
2476
|
+
if (!VALID_DISPOSITIONS.has(rule.is)) {
|
|
2477
|
+
problems.push(
|
|
2478
|
+
`disposition "${rule.is}" is not valid (expected active, blocked, or parked \u2014 terminal is never a rule)`
|
|
2479
|
+
);
|
|
2480
|
+
}
|
|
2481
|
+
if (rule.when !== null) {
|
|
2482
|
+
const err2 = validateWhen(rule.when);
|
|
2483
|
+
if (err2) problems.push(`disposition rule "${rule.is}": invalid condition \u2014 ${err2}`);
|
|
2484
|
+
}
|
|
2485
|
+
}
|
|
2486
|
+
const elseIndices = derive.disposition.map((r, i) => r.when === null ? i : -1).filter((i) => i >= 0);
|
|
2487
|
+
if (elseIndices.length === 0) {
|
|
2488
|
+
problems.push("disposition rules must end with an `else:` arm (a rule with when: null)");
|
|
2489
|
+
} else if (elseIndices.length > 1) {
|
|
2490
|
+
problems.push("disposition rules must have exactly one `else:` arm (when: null)");
|
|
2491
|
+
} else if (elseIndices[0] !== derive.disposition.length - 1) {
|
|
2492
|
+
problems.push("the `else:` arm (when: null) must be the LAST disposition rule \u2014 rules after it are unreachable");
|
|
2493
|
+
}
|
|
2494
|
+
for (const key of ["parked", "blocked"]) {
|
|
2495
|
+
if (!ids.has(derive.headline[key])) {
|
|
2496
|
+
problems.push(
|
|
2497
|
+
`headline.${key} \u2192 "${derive.headline[key]}" is not a defined status id (add the definition or run migrate-derive)`
|
|
2498
|
+
);
|
|
2499
|
+
}
|
|
2500
|
+
}
|
|
2501
|
+
return problems;
|
|
2502
|
+
}
|
|
2503
|
+
var DEFAULT_DERIVE_CONFIG;
|
|
2504
|
+
var init_derive_config = __esm({
|
|
2505
|
+
"src/utils/derive-config.ts"() {
|
|
2506
|
+
"use strict";
|
|
2507
|
+
DEFAULT_DERIVE_CONFIG = {
|
|
2508
|
+
phaseLadder: [
|
|
2509
|
+
{ phase: "draft", when: "*", next: "Fill in the objective and acceptance criteria" },
|
|
2510
|
+
{
|
|
2511
|
+
// planExists-but-not-approved also sits here: the default status set has
|
|
2512
|
+
// no `planning` id. Users who define one add a `planExists:true` rung.
|
|
2513
|
+
phase: "ready_for_planning",
|
|
2514
|
+
when: "hasRealObjective:true AND acRealTotal > 0",
|
|
2515
|
+
next: "Write a plan and get it approved"
|
|
2516
|
+
},
|
|
2517
|
+
{ phase: "ready_to_implement", when: "planApproved:true", next: "Start implementing" },
|
|
2518
|
+
{
|
|
2519
|
+
phase: "in_progress",
|
|
2520
|
+
when: "planApproved:true AND implementationStarted:true",
|
|
2521
|
+
next: "Finish acceptance criteria, then request review"
|
|
2522
|
+
},
|
|
2523
|
+
{
|
|
2524
|
+
phase: "review",
|
|
2525
|
+
when: "acAllChecked:true OR reviewRequested:true",
|
|
2526
|
+
next: "Complete, or address review feedback"
|
|
2527
|
+
}
|
|
2528
|
+
],
|
|
2529
|
+
disposition: [
|
|
2530
|
+
{ when: "parked:true", is: "parked" },
|
|
2531
|
+
{ when: "blocked:true", is: "blocked" },
|
|
2532
|
+
{ when: null, is: "active" }
|
|
2533
|
+
],
|
|
2534
|
+
headline: { terminal: "passthrough", parked: "parked", blocked: "blocked", active: "phase" }
|
|
2535
|
+
};
|
|
2536
|
+
}
|
|
2537
|
+
});
|
|
2538
|
+
|
|
2414
2539
|
// src/utils/query/fields.ts
|
|
2415
2540
|
function resolveField(registry, name) {
|
|
2416
2541
|
return registry[name.toLowerCase()] ?? null;
|
|
@@ -3107,6 +3232,24 @@ function factFieldNames(decl) {
|
|
|
3107
3232
|
].map((k) => k.toLowerCase()) : [exportNames.fact.toLowerCase()];
|
|
3108
3233
|
return { storageKey: name, exports: exportNames, registryKeys };
|
|
3109
3234
|
}
|
|
3235
|
+
function normalizeFactDeclarations(raw2) {
|
|
3236
|
+
const out = [];
|
|
3237
|
+
for (const row of raw2 ?? []) {
|
|
3238
|
+
if (!row || typeof row.name !== "string") continue;
|
|
3239
|
+
const name = row.name.trim();
|
|
3240
|
+
if (!/^[a-z][a-zA-Z0-9]*$/.test(name)) continue;
|
|
3241
|
+
const type = (row.type ?? "").trim();
|
|
3242
|
+
if (type === "bool" || type === "number") {
|
|
3243
|
+
out.push({ name, type });
|
|
3244
|
+
} else if (type === "attestation") {
|
|
3245
|
+
const binds = (row.binds ?? "none").toString().trim() || "none";
|
|
3246
|
+
if (binds === "plan" || binds === "commit" || binds === "none") {
|
|
3247
|
+
out.push({ name, type: "attestation", binds });
|
|
3248
|
+
}
|
|
3249
|
+
}
|
|
3250
|
+
}
|
|
3251
|
+
return out;
|
|
3252
|
+
}
|
|
3110
3253
|
function validateFactDeclarations(raw2) {
|
|
3111
3254
|
const problems = [];
|
|
3112
3255
|
const owners = /* @__PURE__ */ new Map();
|
|
@@ -3356,6 +3499,7 @@ __export(config_exports, {
|
|
|
3356
3499
|
updatePlaybooksConfig: () => updatePlaybooksConfig,
|
|
3357
3500
|
validateAgentList: () => validateAgentList,
|
|
3358
3501
|
validateDeriveConfig: () => validateDeriveConfig,
|
|
3502
|
+
validateDeriveShape: () => validateDeriveShape,
|
|
3359
3503
|
validateFactDeclarations: () => validateFactDeclarations,
|
|
3360
3504
|
writeAgentsConfig: () => writeAgentsConfig,
|
|
3361
3505
|
writeHotkeyBindingsConfig: () => writeHotkeyBindingsConfig,
|
|
@@ -3367,24 +3511,6 @@ __export(config_exports, {
|
|
|
3367
3511
|
import { readFile as readFile5 } from "fs/promises";
|
|
3368
3512
|
import { spawnSync } from "child_process";
|
|
3369
3513
|
import { resolve as resolve6, isAbsolute } from "path";
|
|
3370
|
-
function normalizeFactDeclarations(raw2) {
|
|
3371
|
-
const out = [];
|
|
3372
|
-
for (const row of raw2 ?? []) {
|
|
3373
|
-
if (!row || typeof row.name !== "string") continue;
|
|
3374
|
-
const name = row.name.trim();
|
|
3375
|
-
if (!/^[a-z][a-zA-Z0-9]*$/.test(name)) continue;
|
|
3376
|
-
const type = (row.type ?? "").trim();
|
|
3377
|
-
if (type === "bool" || type === "number") {
|
|
3378
|
-
out.push({ name, type });
|
|
3379
|
-
} else if (type === "attestation") {
|
|
3380
|
-
const binds = (row.binds ?? "none").toString().trim() || "none";
|
|
3381
|
-
if (binds === "plan" || binds === "commit" || binds === "none") {
|
|
3382
|
-
out.push({ name, type: "attestation", binds });
|
|
3383
|
-
}
|
|
3384
|
-
}
|
|
3385
|
-
}
|
|
3386
|
-
return out;
|
|
3387
|
-
}
|
|
3388
3514
|
function parseAgentCommand(value, agentId) {
|
|
3389
3515
|
if (typeof value !== "string" || value.trim() === "") {
|
|
3390
3516
|
throw new AgentConfigError(
|
|
@@ -3778,43 +3904,6 @@ function serializeStatusConfig(statuses) {
|
|
|
3778
3904
|
}
|
|
3779
3905
|
return lines.join("\n");
|
|
3780
3906
|
}
|
|
3781
|
-
function validateDeriveConfig(derive, statusConfig, validateWhen = () => null) {
|
|
3782
|
-
const problems = [];
|
|
3783
|
-
const ids = new Set(statusConfig.statuses.map((s) => s.id));
|
|
3784
|
-
if (derive.phaseLadder.length === 0) {
|
|
3785
|
-
problems.push("phaseLadder must have at least one rung");
|
|
3786
|
-
}
|
|
3787
|
-
for (const rung of derive.phaseLadder) {
|
|
3788
|
-
if (!ids.has(rung.phase)) {
|
|
3789
|
-
problems.push(`phaseLadder rung "${rung.phase}" is not a defined status id`);
|
|
3790
|
-
}
|
|
3791
|
-
const err2 = rung.when === "*" ? null : validateWhen(rung.when);
|
|
3792
|
-
if (err2) problems.push(`phaseLadder rung "${rung.phase}": invalid condition \u2014 ${err2}`);
|
|
3793
|
-
}
|
|
3794
|
-
const VALID_DISPOSITIONS = /* @__PURE__ */ new Set(["active", "blocked", "parked"]);
|
|
3795
|
-
let sawElse = false;
|
|
3796
|
-
for (const rule of derive.disposition) {
|
|
3797
|
-
if (!VALID_DISPOSITIONS.has(rule.is)) {
|
|
3798
|
-
problems.push(
|
|
3799
|
-
`disposition "${rule.is}" is not valid (expected active, blocked, or parked \u2014 terminal is never a rule)`
|
|
3800
|
-
);
|
|
3801
|
-
}
|
|
3802
|
-
if (rule.when === null) sawElse = true;
|
|
3803
|
-
else {
|
|
3804
|
-
const err2 = validateWhen(rule.when);
|
|
3805
|
-
if (err2) problems.push(`disposition rule "${rule.is}": invalid condition \u2014 ${err2}`);
|
|
3806
|
-
}
|
|
3807
|
-
}
|
|
3808
|
-
if (!sawElse) problems.push("disposition rules must end with an `else:` arm");
|
|
3809
|
-
for (const key of ["parked", "blocked"]) {
|
|
3810
|
-
if (!ids.has(derive.headline[key])) {
|
|
3811
|
-
problems.push(
|
|
3812
|
-
`headline.${key} \u2192 "${derive.headline[key]}" is not a defined status id (add the definition or run migrate-derive)`
|
|
3813
|
-
);
|
|
3814
|
-
}
|
|
3815
|
-
}
|
|
3816
|
-
return problems;
|
|
3817
|
-
}
|
|
3818
3907
|
function serializeIntegrationConfig(integrations) {
|
|
3819
3908
|
const lines = [];
|
|
3820
3909
|
if (integrations.claudePluginDir) {
|
|
@@ -4881,7 +4970,7 @@ async function updateAgentsConfig(mutation, options = {}) {
|
|
|
4881
4970
|
await writeAgentsConfig(next);
|
|
4882
4971
|
return { previous, next, written: true };
|
|
4883
4972
|
}
|
|
4884
|
-
var
|
|
4973
|
+
var DEFAULT_ASSIGNMENT_TYPES, DEFAULT_CONFIG, AUTO_CREATE_WORKTREE_VALUES, SESSION_AUTO_TRACK_VALUES, AgentConfigError, DEFAULT_STATUS_COLORS, KNOWN_AGENT_SCALAR_FIELDS, migratedConfigPaths, TerminalConfigError;
|
|
4885
4974
|
var init_config2 = __esm({
|
|
4886
4975
|
"src/utils/config.ts"() {
|
|
4887
4976
|
"use strict";
|
|
@@ -4893,38 +4982,10 @@ var init_config2 = __esm({
|
|
|
4893
4982
|
init_hotkeysCatalog();
|
|
4894
4983
|
init_agents_schema();
|
|
4895
4984
|
init_slug();
|
|
4985
|
+
init_derive_config();
|
|
4896
4986
|
init_fact_registry();
|
|
4897
4987
|
init_terminal_schema();
|
|
4898
4988
|
init_workspace_visibility_schema();
|
|
4899
|
-
DEFAULT_DERIVE_CONFIG = {
|
|
4900
|
-
phaseLadder: [
|
|
4901
|
-
{ phase: "draft", when: "*", next: "Fill in the objective and acceptance criteria" },
|
|
4902
|
-
{
|
|
4903
|
-
// planExists-but-not-approved also sits here: the default status set has
|
|
4904
|
-
// no `planning` id. Users who define one add a `planExists:true` rung.
|
|
4905
|
-
phase: "ready_for_planning",
|
|
4906
|
-
when: "hasRealObjective:true AND acRealTotal > 0",
|
|
4907
|
-
next: "Write a plan and get it approved"
|
|
4908
|
-
},
|
|
4909
|
-
{ phase: "ready_to_implement", when: "planApproved:true", next: "Start implementing" },
|
|
4910
|
-
{
|
|
4911
|
-
phase: "in_progress",
|
|
4912
|
-
when: "planApproved:true AND implementationStarted:true",
|
|
4913
|
-
next: "Finish acceptance criteria, then request review"
|
|
4914
|
-
},
|
|
4915
|
-
{
|
|
4916
|
-
phase: "review",
|
|
4917
|
-
when: "acAllChecked:true OR reviewRequested:true",
|
|
4918
|
-
next: "Complete, or address review feedback"
|
|
4919
|
-
}
|
|
4920
|
-
],
|
|
4921
|
-
disposition: [
|
|
4922
|
-
{ when: "parked:true", is: "parked" },
|
|
4923
|
-
{ when: "blocked:true", is: "blocked" },
|
|
4924
|
-
{ when: null, is: "active" }
|
|
4925
|
-
],
|
|
4926
|
-
headline: { terminal: "passthrough", parked: "parked", blocked: "blocked", active: "phase" }
|
|
4927
|
-
};
|
|
4928
4989
|
DEFAULT_ASSIGNMENT_TYPES = {
|
|
4929
4990
|
definitions: [
|
|
4930
4991
|
{ id: "feature", label: "Feature" },
|
|
@@ -8784,6 +8845,8 @@ async function getStatusConfig() {
|
|
|
8784
8845
|
order: effectiveOrder,
|
|
8785
8846
|
transitions: effectiveTransitions2,
|
|
8786
8847
|
transitionTable: buildTransitionTable(effectiveTransitions2),
|
|
8848
|
+
rawTransitions: sc.transitions,
|
|
8849
|
+
transitionsCustom: hasCustomTransitions,
|
|
8787
8850
|
terminalStatuses: terminalSet.size > 0 ? terminalSet : /* @__PURE__ */ new Set(["completed", "failed"]),
|
|
8788
8851
|
derive: sc.derive ?? null,
|
|
8789
8852
|
facts: sc.facts ?? null,
|
|
@@ -8799,6 +8862,9 @@ async function getStatusConfig() {
|
|
|
8799
8862
|
order: def.order,
|
|
8800
8863
|
transitions: def.transitions,
|
|
8801
8864
|
transitionTable: DEFAULT_TRANSITION_TABLE,
|
|
8865
|
+
// No custom config at all → the Settings editor shows read-only defaults.
|
|
8866
|
+
rawTransitions: [],
|
|
8867
|
+
transitionsCustom: false,
|
|
8802
8868
|
terminalStatuses: /* @__PURE__ */ new Set(["completed", "failed"]),
|
|
8803
8869
|
derive: null,
|
|
8804
8870
|
facts: null,
|
|
@@ -9950,7 +10016,7 @@ async function buildDerivedDetail(assignment, assignmentDir, projectDir) {
|
|
|
9950
10016
|
try {
|
|
9951
10017
|
const { computeFactsDetailed: computeFactsDetailed2 } = await Promise.resolve().then(() => (init_facts(), facts_exports));
|
|
9952
10018
|
const { deriveDimensions: deriveDimensions2 } = await Promise.resolve().then(() => (init_derive(), derive_exports));
|
|
9953
|
-
const { DEFAULT_DERIVE_CONFIG:
|
|
10019
|
+
const { DEFAULT_DERIVE_CONFIG: DEFAULT_DERIVE_CONFIG2 } = await Promise.resolve().then(() => (init_config2(), config_exports));
|
|
9954
10020
|
const { facts, attestations } = await computeFactsDetailed2({
|
|
9955
10021
|
assignmentDir,
|
|
9956
10022
|
frontmatter: {
|
|
@@ -9965,7 +10031,7 @@ async function buildDerivedDetail(assignment, assignmentDir, projectDir) {
|
|
|
9965
10031
|
});
|
|
9966
10032
|
const dims = deriveDimensions2({
|
|
9967
10033
|
facts,
|
|
9968
|
-
derive: config.derive ??
|
|
10034
|
+
derive: config.derive ?? DEFAULT_DERIVE_CONFIG2,
|
|
9969
10035
|
currentStatus: assignment.status,
|
|
9970
10036
|
terminalStatuses: config.terminalStatuses,
|
|
9971
10037
|
knownStatusIds: new Set(config.statuses.map((s) => s.id)),
|
|
@@ -19384,6 +19450,7 @@ function createWorkspaceVisibilityConfigRouter() {
|
|
|
19384
19450
|
// src/dashboard/api-status-config.ts
|
|
19385
19451
|
init_config2();
|
|
19386
19452
|
init_fact_registry();
|
|
19453
|
+
init_state_machine();
|
|
19387
19454
|
init_api();
|
|
19388
19455
|
init_derive();
|
|
19389
19456
|
import { Router as Router9 } from "express";
|
|
@@ -19715,6 +19782,25 @@ function buildAffectedResponse(id, list) {
|
|
|
19715
19782
|
function isString(x) {
|
|
19716
19783
|
return typeof x === "string" && x.length > 0;
|
|
19717
19784
|
}
|
|
19785
|
+
function configResponse(config) {
|
|
19786
|
+
return {
|
|
19787
|
+
statuses: config.statuses,
|
|
19788
|
+
order: config.order,
|
|
19789
|
+
// RAW transitions (empty when the user has none) + a custom flag, so the
|
|
19790
|
+
// Settings editor can show read-only defaults vs. a customized table. The
|
|
19791
|
+
// materialized `config.transitions` (default-filled for runtime guards) is
|
|
19792
|
+
// deliberately NOT exposed here — sending it would make the defaults view
|
|
19793
|
+
// unreachable and round-trip phantom rows for undefined statuses.
|
|
19794
|
+
transitions: config.rawTransitions,
|
|
19795
|
+
transitionsCustom: config.transitionsCustom,
|
|
19796
|
+
custom: config.custom,
|
|
19797
|
+
derive: config.derive ?? DEFAULT_DERIVE_CONFIG,
|
|
19798
|
+
deriveCustom: config.derive !== null,
|
|
19799
|
+
knownCommands: [...DEFAULT_COMMAND_TARGETS.keys()],
|
|
19800
|
+
factDeclarations: config.factDeclarations,
|
|
19801
|
+
rawFacts: config.facts ?? []
|
|
19802
|
+
};
|
|
19803
|
+
}
|
|
19718
19804
|
function parseResolutions(raw2) {
|
|
19719
19805
|
if (raw2 === void 0) {
|
|
19720
19806
|
return { resolutions: [], malformed: null, duplicateIds: null };
|
|
@@ -19788,14 +19874,7 @@ function createStatusConfigRouter(projectsDir2, assignmentsDir2) {
|
|
|
19788
19874
|
router.get("/", async (_req, res) => {
|
|
19789
19875
|
try {
|
|
19790
19876
|
const config = await getStatusConfig();
|
|
19791
|
-
res.json(
|
|
19792
|
-
statuses: config.statuses,
|
|
19793
|
-
order: config.order,
|
|
19794
|
-
transitions: config.transitions,
|
|
19795
|
-
custom: config.custom,
|
|
19796
|
-
factDeclarations: config.factDeclarations,
|
|
19797
|
-
rawFacts: config.facts ?? []
|
|
19798
|
-
});
|
|
19877
|
+
res.json(configResponse(config));
|
|
19799
19878
|
} catch (error) {
|
|
19800
19879
|
console.error("Error getting status config:", error);
|
|
19801
19880
|
res.status(500).json({ error: "Failed to get status config" });
|
|
@@ -19822,6 +19901,7 @@ function createStatusConfigRouter(projectsDir2, assignmentsDir2) {
|
|
|
19822
19901
|
statuses,
|
|
19823
19902
|
order,
|
|
19824
19903
|
transitions,
|
|
19904
|
+
derive,
|
|
19825
19905
|
facts: bodyFacts,
|
|
19826
19906
|
factRemovalAcks,
|
|
19827
19907
|
resolutions: rawResolutions
|
|
@@ -19831,17 +19911,26 @@ function createStatusConfigRouter(projectsDir2, assignmentsDir2) {
|
|
|
19831
19911
|
const hasStatuses = statuses !== void 0;
|
|
19832
19912
|
const hasOrder = order !== void 0;
|
|
19833
19913
|
const hasTransitions = transitions !== void 0;
|
|
19834
|
-
|
|
19835
|
-
|
|
19836
|
-
|
|
19837
|
-
|
|
19838
|
-
|
|
19839
|
-
|
|
19840
|
-
|
|
19841
|
-
|
|
19842
|
-
|
|
19914
|
+
const hasDerive = derive !== void 0;
|
|
19915
|
+
if (!hasStatuses && !hasOrder && !hasTransitions && !hasFacts && !hasDerive) {
|
|
19916
|
+
res.status(400).json({ error: "malformed-statuses", message: "Request body must include at least one of statuses, order, transitions, derive, or facts" });
|
|
19917
|
+
return;
|
|
19918
|
+
}
|
|
19919
|
+
if (hasStatuses && !Array.isArray(statuses)) {
|
|
19920
|
+
res.status(400).json({ error: "malformed-statuses", message: "statuses must be an array" });
|
|
19921
|
+
return;
|
|
19922
|
+
}
|
|
19923
|
+
if (hasOrder && !Array.isArray(order)) {
|
|
19924
|
+
res.status(400).json({ error: "malformed-statuses", message: "order must be an array" });
|
|
19843
19925
|
return;
|
|
19844
19926
|
}
|
|
19927
|
+
if (hasTransitions && !Array.isArray(transitions)) {
|
|
19928
|
+
res.status(400).json({ error: "malformed-transitions", message: "transitions must be an array" });
|
|
19929
|
+
return;
|
|
19930
|
+
}
|
|
19931
|
+
const effectiveStatuses = hasStatuses ? statuses : currentConfig.statuses;
|
|
19932
|
+
const effectiveOrder = hasOrder ? order : currentConfig.order;
|
|
19933
|
+
const effectiveTransitions2 = hasTransitions ? transitions : currentConfig.rawTransitions;
|
|
19845
19934
|
const parsed = parseResolutions(rawResolutions);
|
|
19846
19935
|
if (parsed.malformed) {
|
|
19847
19936
|
res.status(400).json({ error: "malformed-resolutions", message: parsed.malformed });
|
|
@@ -19888,60 +19977,13 @@ function createStatusConfigRouter(projectsDir2, assignmentsDir2) {
|
|
|
19888
19977
|
return;
|
|
19889
19978
|
}
|
|
19890
19979
|
}
|
|
19891
|
-
let affectedMap;
|
|
19892
|
-
try {
|
|
19893
|
-
affectedMap = await scanAssignmentsByStatus(projectsDir2, assignmentsDir2, droppedIds);
|
|
19894
|
-
} catch (err2) {
|
|
19895
|
-
if (err2 instanceof StatusResolutionError) {
|
|
19896
|
-
const mapped = mapResolutionErrorToHttp(err2, null);
|
|
19897
|
-
res.status(mapped.status).json(mapped.body);
|
|
19898
|
-
return;
|
|
19899
|
-
}
|
|
19900
|
-
throw err2;
|
|
19901
|
-
}
|
|
19902
|
-
const unresolved = [];
|
|
19903
|
-
const resolvedById = new Set(resolutions.map((r) => r.id));
|
|
19904
|
-
for (const id of droppedIds) {
|
|
19905
|
-
const list = affectedMap.get(id) ?? [];
|
|
19906
|
-
if (list.length > 0 && !resolvedById.has(id)) {
|
|
19907
|
-
unresolved.push(buildAffectedResponse(id, list));
|
|
19908
|
-
}
|
|
19909
|
-
}
|
|
19910
|
-
if (unresolved.length > 0) {
|
|
19911
|
-
res.status(409).json({ error: "unresolved-orphans", unresolved });
|
|
19912
|
-
return;
|
|
19913
|
-
}
|
|
19914
|
-
let applied;
|
|
19915
|
-
try {
|
|
19916
|
-
applied = await applyStatusResolutions(resolutions, affectedMap, validTargets);
|
|
19917
|
-
} catch (err2) {
|
|
19918
|
-
if (err2 instanceof StatusResolutionError) {
|
|
19919
|
-
const mapped = mapResolutionErrorToHttp(err2, null);
|
|
19920
|
-
res.status(mapped.status).json(mapped.body);
|
|
19921
|
-
return;
|
|
19922
|
-
}
|
|
19923
|
-
throw err2;
|
|
19924
|
-
}
|
|
19925
|
-
try {
|
|
19926
|
-
await verifyNoDriftedOrphans(projectsDir2, assignmentsDir2, droppedIds);
|
|
19927
|
-
} catch (err2) {
|
|
19928
|
-
if (err2 instanceof StatusResolutionError) {
|
|
19929
|
-
const mapped = mapResolutionErrorToHttp(err2, {
|
|
19930
|
-
remapped: applied.remapped,
|
|
19931
|
-
deleted: applied.deleted
|
|
19932
|
-
});
|
|
19933
|
-
res.status(mapped.status).json(mapped.body);
|
|
19934
|
-
return;
|
|
19935
|
-
}
|
|
19936
|
-
throw err2;
|
|
19937
|
-
}
|
|
19938
19980
|
let factsToWrite = currentConfig.facts ?? null;
|
|
19939
19981
|
if (hasFacts) {
|
|
19940
|
-
const shapedFacts = [];
|
|
19941
19982
|
if (!Array.isArray(bodyFacts)) {
|
|
19942
19983
|
res.status(400).json({ error: "malformed-facts", message: "facts must be an array" });
|
|
19943
19984
|
return;
|
|
19944
19985
|
}
|
|
19986
|
+
const shapedFacts = [];
|
|
19945
19987
|
for (let i = 0; i < bodyFacts.length; i++) {
|
|
19946
19988
|
const row = bodyFacts[i];
|
|
19947
19989
|
if (!row || typeof row !== "object") {
|
|
@@ -19963,24 +20005,73 @@ function createStatusConfigRouter(projectsDir2, assignmentsDir2) {
|
|
|
19963
20005
|
res.status(400).json({ error: "invalid-facts", problems });
|
|
19964
20006
|
return;
|
|
19965
20007
|
}
|
|
20008
|
+
factsToWrite = shapedFacts;
|
|
20009
|
+
}
|
|
20010
|
+
let effectiveDerive = currentConfig.derive ?? null;
|
|
20011
|
+
if (hasDerive) {
|
|
20012
|
+
if (derive === null) {
|
|
20013
|
+
effectiveDerive = null;
|
|
20014
|
+
} else {
|
|
20015
|
+
const shapeProblems = validateDeriveShape(derive);
|
|
20016
|
+
if (shapeProblems.length > 0) {
|
|
20017
|
+
res.status(400).json({ error: "invalid-derive", problems: shapeProblems });
|
|
20018
|
+
return;
|
|
20019
|
+
}
|
|
20020
|
+
const incomingRegistry = buildDeriveRegistry(
|
|
20021
|
+
acceptFactDeclarations(normalizeFactDeclarations(factsToWrite))
|
|
20022
|
+
);
|
|
20023
|
+
const problems = validateDeriveConfig(
|
|
20024
|
+
derive,
|
|
20025
|
+
{ statuses: effectiveStatuses },
|
|
20026
|
+
(when) => validateDeriveCondition(when, incomingRegistry)
|
|
20027
|
+
);
|
|
20028
|
+
if (problems.length > 0) {
|
|
20029
|
+
res.status(400).json({ error: "invalid-derive", problems });
|
|
20030
|
+
return;
|
|
20031
|
+
}
|
|
20032
|
+
effectiveDerive = derive;
|
|
20033
|
+
}
|
|
20034
|
+
}
|
|
20035
|
+
if (hasTransitions) {
|
|
20036
|
+
for (let i = 0; i < transitions.length; i++) {
|
|
20037
|
+
const t = transitions[i];
|
|
20038
|
+
const ok = !!t && typeof t === "object" && typeof t.from === "string" && typeof t.command === "string" && typeof t.to === "string" && (t.label === void 0 || typeof t.label === "string") && (t.description === void 0 || typeof t.description === "string") && (t.requiresReason === void 0 || typeof t.requiresReason === "boolean");
|
|
20039
|
+
if (!ok) {
|
|
20040
|
+
res.status(400).json({
|
|
20041
|
+
error: "invalid-transitions",
|
|
20042
|
+
problems: [`transitions[${i}] must have string from/command/to (+ optional string label/description, boolean requiresReason)`]
|
|
20043
|
+
});
|
|
20044
|
+
return;
|
|
20045
|
+
}
|
|
20046
|
+
}
|
|
20047
|
+
const tproblems = [];
|
|
20048
|
+
for (const t of transitions) {
|
|
20049
|
+
if (!newIds.has(t.from)) tproblems.push(`transition ${t.from} --${t.command}--> ${t.to}: "${t.from}" is not a defined status`);
|
|
20050
|
+
if (!newIds.has(t.to)) tproblems.push(`transition ${t.from} --${t.command}--> ${t.to}: "${t.to}" is not a defined status`);
|
|
20051
|
+
}
|
|
20052
|
+
if (tproblems.length > 0) {
|
|
20053
|
+
res.status(400).json({ error: "invalid-transitions", problems: tproblems });
|
|
20054
|
+
return;
|
|
20055
|
+
}
|
|
20056
|
+
}
|
|
20057
|
+
if (hasFacts) {
|
|
19966
20058
|
const currentNames = new Set((currentConfig.facts ?? []).map((f) => f.name));
|
|
19967
|
-
const incomingNames = new Set(
|
|
20059
|
+
const incomingNames = new Set((factsToWrite ?? []).map((f) => f.name));
|
|
19968
20060
|
const removedNames = [];
|
|
19969
20061
|
for (const name of currentNames) {
|
|
19970
20062
|
if (!incomingNames.has(name)) removedNames.push(name);
|
|
19971
20063
|
}
|
|
19972
20064
|
const acks = new Set(Array.isArray(factRemovalAcks) ? factRemovalAcks.map((x) => String(x)) : []);
|
|
19973
20065
|
const unresolvedRefs = [];
|
|
19974
|
-
|
|
19975
|
-
if (deriveConfig !== null && removedNames.length > 0) {
|
|
20066
|
+
if (effectiveDerive !== null && removedNames.length > 0) {
|
|
19976
20067
|
const acceptedAll = acceptFactDeclarations(normalizeFactDeclarations(currentConfig.facts));
|
|
19977
20068
|
const fullRegistry = buildDeriveRegistry(acceptedAll);
|
|
19978
20069
|
for (const removedName of removedNames) {
|
|
19979
20070
|
if (acks.has(removedName)) continue;
|
|
19980
20071
|
const acceptedWithout = acceptedAll.filter((d) => d.name !== removedName);
|
|
19981
20072
|
const withoutRegistry = buildDeriveRegistry(acceptedWithout);
|
|
19982
|
-
for (let i = 0; i <
|
|
19983
|
-
const rung =
|
|
20073
|
+
for (let i = 0; i < effectiveDerive.phaseLadder.length; i++) {
|
|
20074
|
+
const rung = effectiveDerive.phaseLadder[i];
|
|
19984
20075
|
if (rung.when === "*") continue;
|
|
19985
20076
|
const before = validateDeriveCondition(rung.when, fullRegistry);
|
|
19986
20077
|
const after = validateDeriveCondition(rung.when, withoutRegistry);
|
|
@@ -19988,8 +20079,8 @@ function createStatusConfigRouter(projectsDir2, assignmentsDir2) {
|
|
|
19988
20079
|
unresolvedRefs.push({ factName: removedName, location: `phaseLadder[${i}]`, when: rung.when });
|
|
19989
20080
|
}
|
|
19990
20081
|
}
|
|
19991
|
-
for (let i = 0; i <
|
|
19992
|
-
const rule =
|
|
20082
|
+
for (let i = 0; i < effectiveDerive.disposition.length; i++) {
|
|
20083
|
+
const rule = effectiveDerive.disposition[i];
|
|
19993
20084
|
if (rule.when === null) continue;
|
|
19994
20085
|
const before = validateDeriveCondition(rule.when, fullRegistry);
|
|
19995
20086
|
const after = validateDeriveCondition(rule.when, withoutRegistry);
|
|
@@ -20003,14 +20094,60 @@ function createStatusConfigRouter(projectsDir2, assignmentsDir2) {
|
|
|
20003
20094
|
res.status(409).json({ error: "unresolved-fact-references", references: unresolvedRefs });
|
|
20004
20095
|
return;
|
|
20005
20096
|
}
|
|
20006
|
-
|
|
20097
|
+
}
|
|
20098
|
+
let affectedMap;
|
|
20099
|
+
try {
|
|
20100
|
+
affectedMap = await scanAssignmentsByStatus(projectsDir2, assignmentsDir2, droppedIds);
|
|
20101
|
+
} catch (err2) {
|
|
20102
|
+
if (err2 instanceof StatusResolutionError) {
|
|
20103
|
+
const mapped = mapResolutionErrorToHttp(err2, null);
|
|
20104
|
+
res.status(mapped.status).json(mapped.body);
|
|
20105
|
+
return;
|
|
20106
|
+
}
|
|
20107
|
+
throw err2;
|
|
20108
|
+
}
|
|
20109
|
+
const unresolved = [];
|
|
20110
|
+
const resolvedById = new Set(resolutions.map((r) => r.id));
|
|
20111
|
+
for (const id of droppedIds) {
|
|
20112
|
+
const list = affectedMap.get(id) ?? [];
|
|
20113
|
+
if (list.length > 0 && !resolvedById.has(id)) {
|
|
20114
|
+
unresolved.push(buildAffectedResponse(id, list));
|
|
20115
|
+
}
|
|
20116
|
+
}
|
|
20117
|
+
if (unresolved.length > 0) {
|
|
20118
|
+
res.status(409).json({ error: "unresolved-orphans", unresolved });
|
|
20119
|
+
return;
|
|
20120
|
+
}
|
|
20121
|
+
let applied;
|
|
20122
|
+
try {
|
|
20123
|
+
applied = await applyStatusResolutions(resolutions, affectedMap, validTargets);
|
|
20124
|
+
} catch (err2) {
|
|
20125
|
+
if (err2 instanceof StatusResolutionError) {
|
|
20126
|
+
const mapped = mapResolutionErrorToHttp(err2, null);
|
|
20127
|
+
res.status(mapped.status).json(mapped.body);
|
|
20128
|
+
return;
|
|
20129
|
+
}
|
|
20130
|
+
throw err2;
|
|
20131
|
+
}
|
|
20132
|
+
try {
|
|
20133
|
+
await verifyNoDriftedOrphans(projectsDir2, assignmentsDir2, droppedIds);
|
|
20134
|
+
} catch (err2) {
|
|
20135
|
+
if (err2 instanceof StatusResolutionError) {
|
|
20136
|
+
const mapped = mapResolutionErrorToHttp(err2, {
|
|
20137
|
+
remapped: applied.remapped,
|
|
20138
|
+
deleted: applied.deleted
|
|
20139
|
+
});
|
|
20140
|
+
res.status(mapped.status).json(mapped.body);
|
|
20141
|
+
return;
|
|
20142
|
+
}
|
|
20143
|
+
throw err2;
|
|
20007
20144
|
}
|
|
20008
20145
|
try {
|
|
20009
20146
|
await writeStatusConfig({
|
|
20010
20147
|
statuses: effectiveStatuses,
|
|
20011
20148
|
order: effectiveOrder,
|
|
20012
20149
|
transitions: effectiveTransitions2,
|
|
20013
|
-
derive:
|
|
20150
|
+
derive: effectiveDerive,
|
|
20014
20151
|
facts: factsToWrite
|
|
20015
20152
|
});
|
|
20016
20153
|
} catch (err2) {
|
|
@@ -20029,10 +20166,7 @@ function createStatusConfigRouter(projectsDir2, assignmentsDir2) {
|
|
|
20029
20166
|
byId[id] = entry.target !== void 0 ? { mode: entry.mode, count: entry.count, target: entry.target } : { mode: entry.mode, count: entry.count };
|
|
20030
20167
|
}
|
|
20031
20168
|
res.json({
|
|
20032
|
-
|
|
20033
|
-
order: config.order,
|
|
20034
|
-
transitions: config.transitions,
|
|
20035
|
-
custom: config.custom,
|
|
20169
|
+
...configResponse(config),
|
|
20036
20170
|
applied: { remapped: applied.remapped, deleted: applied.deleted, byId }
|
|
20037
20171
|
});
|
|
20038
20172
|
} catch (error) {
|
|
@@ -20045,12 +20179,7 @@ function createStatusConfigRouter(projectsDir2, assignmentsDir2) {
|
|
|
20045
20179
|
await deleteStatusConfig();
|
|
20046
20180
|
clearStatusConfigCache();
|
|
20047
20181
|
const config = await getStatusConfig();
|
|
20048
|
-
res.json(
|
|
20049
|
-
statuses: config.statuses,
|
|
20050
|
-
order: config.order,
|
|
20051
|
-
transitions: config.transitions,
|
|
20052
|
-
custom: config.custom
|
|
20053
|
-
});
|
|
20182
|
+
res.json(configResponse(config));
|
|
20054
20183
|
} catch (error) {
|
|
20055
20184
|
console.error("Error resetting status config:", error);
|
|
20056
20185
|
res.status(500).json({ error: "Failed to reset status config" });
|