syntaur 0.46.0 → 0.48.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-RQBuJKcX.js → _basePickBy-Cie7FXcV.js} +1 -1
- package/dashboard/dist/assets/{_baseUniq-_J7s4kD3.js → _baseUniq-C2af7-lW.js} +1 -1
- package/dashboard/dist/assets/{arc-_9SyUgKQ.js → arc-BHKGjEv8.js} +1 -1
- package/dashboard/dist/assets/{architectureDiagram-2XIMDMQ5-C8LeFMgr.js → architectureDiagram-2XIMDMQ5-CWqzcG1t.js} +1 -1
- package/dashboard/dist/assets/{blockDiagram-WCTKOSBZ-gMh0EPEh.js → blockDiagram-WCTKOSBZ-CHLC0M63.js} +1 -1
- package/dashboard/dist/assets/{c4Diagram-IC4MRINW-cHwecwLI.js → c4Diagram-IC4MRINW-Bx6GTZzJ.js} +1 -1
- package/dashboard/dist/assets/channel-CXlttLwe.js +1 -0
- package/dashboard/dist/assets/{chunk-4BX2VUAB-Bb2anYuQ.js → chunk-4BX2VUAB-7cTgwG6c.js} +1 -1
- package/dashboard/dist/assets/{chunk-55IACEB6-DYIRGzA1.js → chunk-55IACEB6-DQmdA20e.js} +1 -1
- package/dashboard/dist/assets/{chunk-FMBD7UC4-sgRWBbaF.js → chunk-FMBD7UC4-knmOnIKI.js} +1 -1
- package/dashboard/dist/assets/{chunk-JSJVCQXG-DlYKMl_j.js → chunk-JSJVCQXG-CaiLHJFn.js} +1 -1
- package/dashboard/dist/assets/{chunk-KX2RTZJC-D0YDLAOF.js → chunk-KX2RTZJC-Crp4zWuY.js} +1 -1
- package/dashboard/dist/assets/{chunk-NQ4KR5QH-D-Y-CUx6.js → chunk-NQ4KR5QH-DDjtdNaK.js} +1 -1
- package/dashboard/dist/assets/{chunk-QZHKN3VN-D7FpSvb5.js → chunk-QZHKN3VN-Cbm1IieP.js} +1 -1
- package/dashboard/dist/assets/{chunk-WL4C6EOR-CtXgQLdS.js → chunk-WL4C6EOR-CdrRh6R4.js} +1 -1
- package/dashboard/dist/assets/classDiagram-VBA2DB6C-BJM0Dprk.js +1 -0
- package/dashboard/dist/assets/classDiagram-v2-RAHNMMFH-BJM0Dprk.js +1 -0
- package/dashboard/dist/assets/clone-BTq7ueDt.js +1 -0
- package/dashboard/dist/assets/{cose-bilkent-S5V4N54A-YbTaohoJ.js → cose-bilkent-S5V4N54A-DyNajnMF.js} +1 -1
- package/dashboard/dist/assets/{dagre-KLK3FWXG-CMtwGAnP.js → dagre-KLK3FWXG-CIBjpfqE.js} +1 -1
- package/dashboard/dist/assets/{diagram-E7M64L7V-D8wBMBAX.js → diagram-E7M64L7V-CDENlpZN.js} +1 -1
- package/dashboard/dist/assets/{diagram-IFDJBPK2-DfudLpiJ.js → diagram-IFDJBPK2-CIGMJoFB.js} +1 -1
- package/dashboard/dist/assets/{diagram-P4PSJMXO-CyMy61wE.js → diagram-P4PSJMXO-C27fj5wp.js} +1 -1
- package/dashboard/dist/assets/{erDiagram-INFDFZHY-BlB4ZQl9.js → erDiagram-INFDFZHY-M2CywJym.js} +1 -1
- package/dashboard/dist/assets/{flowDiagram-PKNHOUZH-DbhDQJM3.js → flowDiagram-PKNHOUZH-CTV6ROYf.js} +1 -1
- package/dashboard/dist/assets/{ganttDiagram-A5KZAMGK-DJFqteNi.js → ganttDiagram-A5KZAMGK-CxH3f3e5.js} +1 -1
- package/dashboard/dist/assets/{gitGraphDiagram-K3NZZRJ6-D8etA_mm.js → gitGraphDiagram-K3NZZRJ6-CwhnVvHE.js} +1 -1
- package/dashboard/dist/assets/{graph-Ce86jeZn.js → graph-DGkI_ekZ.js} +1 -1
- package/dashboard/dist/assets/{index-DzHQIE2n.css → index-BxO2I5dN.css} +1 -1
- package/dashboard/dist/assets/index-CTdFARW9.js +567 -0
- package/dashboard/dist/assets/{infoDiagram-LFFYTUFH-Cx35U-h8.js → infoDiagram-LFFYTUFH-CuKReAi2.js} +1 -1
- package/dashboard/dist/assets/{ishikawaDiagram-PHBUUO56-C04Y2nj8.js → ishikawaDiagram-PHBUUO56-DyBMt5Mw.js} +1 -1
- package/dashboard/dist/assets/{journeyDiagram-4ABVD52K-D8-cxbxE.js → journeyDiagram-4ABVD52K-CnwtbTNs.js} +1 -1
- package/dashboard/dist/assets/{kanban-definition-K7BYSVSG-DVKqMylP.js → kanban-definition-K7BYSVSG-5Sh1bC5j.js} +1 -1
- package/dashboard/dist/assets/{layout-98xZDpgu.js → layout-W2Vytcip.js} +1 -1
- package/dashboard/dist/assets/{linear-0jk_IwAc.js → linear-UTm9E6c4.js} +1 -1
- package/dashboard/dist/assets/{mermaid.core-C337VWfr.js → mermaid.core-B0EB-dBk.js} +4 -4
- package/dashboard/dist/assets/{mindmap-definition-YRQLILUH-8sNYGYEP.js → mindmap-definition-YRQLILUH-CH4L08eg.js} +1 -1
- package/dashboard/dist/assets/{pieDiagram-SKSYHLDU-afcmzHxf.js → pieDiagram-SKSYHLDU-CQ3PMl-w.js} +1 -1
- package/dashboard/dist/assets/{quadrantDiagram-337W2JSQ-B4RjcpOq.js → quadrantDiagram-337W2JSQ-DbZgXUm5.js} +1 -1
- package/dashboard/dist/assets/{requirementDiagram-Z7DCOOCP-CRavU6cI.js → requirementDiagram-Z7DCOOCP-CxJWytQa.js} +1 -1
- package/dashboard/dist/assets/{sankeyDiagram-WA2Y5GQK-DFomU3z-.js → sankeyDiagram-WA2Y5GQK-3YeEasvh.js} +1 -1
- package/dashboard/dist/assets/{sequenceDiagram-2WXFIKYE-CGKO7nmK.js → sequenceDiagram-2WXFIKYE-F2EyvYsW.js} +1 -1
- package/dashboard/dist/assets/{stateDiagram-RAJIS63D-BjFI1K8h.js → stateDiagram-RAJIS63D-DrmiemaD.js} +1 -1
- package/dashboard/dist/assets/stateDiagram-v2-FVOUBMTO-DfyvP5EF.js +1 -0
- package/dashboard/dist/assets/{timeline-definition-YZTLITO2-BBo8XJFG.js → timeline-definition-YZTLITO2-CBee2YiE.js} +1 -1
- package/dashboard/dist/assets/{treemap-KZPCXAKY-COd6i6TE.js → treemap-KZPCXAKY-BkPRIS3K.js} +1 -1
- package/dashboard/dist/assets/{vennDiagram-LZ73GAT5-CGQweQ36.js → vennDiagram-LZ73GAT5-CTsfwv8G.js} +1 -1
- package/dashboard/dist/assets/{xychartDiagram-JWTSCODW-mfJ5So7N.js → xychartDiagram-JWTSCODW-DUSo-c6w.js} +1 -1
- package/dashboard/dist/index.html +2 -2
- package/dist/dashboard/server.js +188 -73
- package/dist/dashboard/server.js.map +1 -1
- package/dist/index.js +198 -74
- package/dist/index.js.map +1 -1
- package/dist/launch/index.d.ts +25 -12
- package/dist/launch/index.js +62 -58
- 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 +7 -0
- package/platforms/codex/.codex-plugin/plugin.json +1 -1
- package/platforms/codex/skills/manage-statuses/SKILL.md +7 -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 +7 -0
- package/dashboard/dist/assets/channel-C36dnl_e.js +0 -1
- package/dashboard/dist/assets/classDiagram-VBA2DB6C-BsoGa6_a.js +0 -1
- package/dashboard/dist/assets/classDiagram-v2-RAHNMMFH-BsoGa6_a.js +0 -1
- package/dashboard/dist/assets/clone-Bz6jW3OY.js +0 -1
- package/dashboard/dist/assets/index-DRng26Jg.js +0 -567
- package/dashboard/dist/assets/stateDiagram-v2-FVOUBMTO-BtxefYKD.js +0 -1
package/dist/index.js
CHANGED
|
@@ -3107,6 +3107,53 @@ function factFieldNames(decl) {
|
|
|
3107
3107
|
].map((k) => k.toLowerCase()) : [exportNames.fact.toLowerCase()];
|
|
3108
3108
|
return { storageKey: name, exports: exportNames, registryKeys };
|
|
3109
3109
|
}
|
|
3110
|
+
function validateFactDeclarations(raw2) {
|
|
3111
|
+
const problems = [];
|
|
3112
|
+
const owners = /* @__PURE__ */ new Map();
|
|
3113
|
+
for (const key of Object.keys(DERIVE_FIELDS)) owners.set(key, "built-in");
|
|
3114
|
+
for (const key of Object.keys(ASSIGNMENT_FIELDS)) owners.set(key, "built-in");
|
|
3115
|
+
for (const row of raw2 ?? []) {
|
|
3116
|
+
const name = (row?.name ?? "").trim();
|
|
3117
|
+
if (!/^[a-z][a-zA-Z0-9]*$/.test(name)) {
|
|
3118
|
+
problems.push(
|
|
3119
|
+
`fact "${row?.name ?? ""}": invalid name \u2014 must match /^[a-z][a-zA-Z0-9]*$/`
|
|
3120
|
+
);
|
|
3121
|
+
continue;
|
|
3122
|
+
}
|
|
3123
|
+
const type = (row.type ?? "").trim();
|
|
3124
|
+
if (type !== "bool" && type !== "number" && type !== "attestation") {
|
|
3125
|
+
problems.push(
|
|
3126
|
+
`fact "${name}": invalid type "${row.type ?? ""}" \u2014 expected bool, number, or attestation`
|
|
3127
|
+
);
|
|
3128
|
+
continue;
|
|
3129
|
+
}
|
|
3130
|
+
if (type === "attestation") {
|
|
3131
|
+
const binds = (row.binds ?? "none").toString().trim() || "none";
|
|
3132
|
+
if (binds !== "plan" && binds !== "commit" && binds !== "none") {
|
|
3133
|
+
problems.push(
|
|
3134
|
+
`fact "${name}": invalid binds "${row.binds}" \u2014 expected plan, commit, or none`
|
|
3135
|
+
);
|
|
3136
|
+
continue;
|
|
3137
|
+
}
|
|
3138
|
+
}
|
|
3139
|
+
const decl = type === "attestation" ? { name, type, binds: "none" } : { name, type };
|
|
3140
|
+
const keys = factFieldNames(decl).registryKeys;
|
|
3141
|
+
const collidingKey = keys.find((k) => owners.has(k));
|
|
3142
|
+
if (collidingKey !== void 0) {
|
|
3143
|
+
const owner = owners.get(collidingKey);
|
|
3144
|
+
if (owner === "built-in") {
|
|
3145
|
+
problems.push(`fact "${name}": exported field "${collidingKey}" collides with a built-in field`);
|
|
3146
|
+
} else if (owner === name) {
|
|
3147
|
+
problems.push(`fact "${name}": duplicate declaration (a fact named "${name}" is already declared)`);
|
|
3148
|
+
} else {
|
|
3149
|
+
problems.push(`fact "${name}": exported field "${collidingKey}" collides with fact "${owner}"`);
|
|
3150
|
+
}
|
|
3151
|
+
continue;
|
|
3152
|
+
}
|
|
3153
|
+
for (const key of keys) owners.set(key, name);
|
|
3154
|
+
}
|
|
3155
|
+
return problems;
|
|
3156
|
+
}
|
|
3110
3157
|
function acceptFactDeclarations(declarations) {
|
|
3111
3158
|
const taken = /* @__PURE__ */ new Set([
|
|
3112
3159
|
...Object.keys(DERIVE_FIELDS),
|
|
@@ -3632,7 +3679,6 @@ function parseStatusConfig(content) {
|
|
|
3632
3679
|
continue;
|
|
3633
3680
|
}
|
|
3634
3681
|
}
|
|
3635
|
-
if (statuses.length === 0) return null;
|
|
3636
3682
|
const derive = phaseLadder.length > 0 || disposition.length > 0 || Object.keys(headline).length > 0 ? {
|
|
3637
3683
|
phaseLadder: phaseLadder.length > 0 ? phaseLadder : DEFAULT_DERIVE_CONFIG.phaseLadder,
|
|
3638
3684
|
disposition: disposition.length > 0 ? disposition : DEFAULT_DERIVE_CONFIG.disposition,
|
|
@@ -3643,6 +3689,7 @@ function parseStatusConfig(content) {
|
|
|
3643
3689
|
active: "phase"
|
|
3644
3690
|
}
|
|
3645
3691
|
} : null;
|
|
3692
|
+
if (statuses.length === 0 && facts.length === 0 && derive === null) return null;
|
|
3646
3693
|
return {
|
|
3647
3694
|
statuses,
|
|
3648
3695
|
order: order.length > 0 ? order : statuses.map((s) => s.id),
|
|
@@ -3768,53 +3815,6 @@ function validateDeriveConfig(derive, statusConfig, validateWhen = () => null) {
|
|
|
3768
3815
|
}
|
|
3769
3816
|
return problems;
|
|
3770
3817
|
}
|
|
3771
|
-
function validateFactDeclarations(raw2) {
|
|
3772
|
-
const problems = [];
|
|
3773
|
-
const owners = /* @__PURE__ */ new Map();
|
|
3774
|
-
for (const key of Object.keys(DERIVE_FIELDS)) owners.set(key, "built-in");
|
|
3775
|
-
for (const key of Object.keys(ASSIGNMENT_FIELDS)) owners.set(key, "built-in");
|
|
3776
|
-
for (const row of raw2 ?? []) {
|
|
3777
|
-
const name = (row?.name ?? "").trim();
|
|
3778
|
-
if (!/^[a-z][a-zA-Z0-9]*$/.test(name)) {
|
|
3779
|
-
problems.push(
|
|
3780
|
-
`fact "${row?.name ?? ""}": invalid name \u2014 must match /^[a-z][a-zA-Z0-9]*$/`
|
|
3781
|
-
);
|
|
3782
|
-
continue;
|
|
3783
|
-
}
|
|
3784
|
-
const type = (row.type ?? "").trim();
|
|
3785
|
-
if (type !== "bool" && type !== "number" && type !== "attestation") {
|
|
3786
|
-
problems.push(
|
|
3787
|
-
`fact "${name}": invalid type "${row.type ?? ""}" \u2014 expected bool, number, or attestation`
|
|
3788
|
-
);
|
|
3789
|
-
continue;
|
|
3790
|
-
}
|
|
3791
|
-
if (type === "attestation") {
|
|
3792
|
-
const binds = (row.binds ?? "none").toString().trim() || "none";
|
|
3793
|
-
if (binds !== "plan" && binds !== "commit" && binds !== "none") {
|
|
3794
|
-
problems.push(
|
|
3795
|
-
`fact "${name}": invalid binds "${row.binds}" \u2014 expected plan, commit, or none`
|
|
3796
|
-
);
|
|
3797
|
-
continue;
|
|
3798
|
-
}
|
|
3799
|
-
}
|
|
3800
|
-
const decl = type === "attestation" ? { name, type, binds: "none" } : { name, type };
|
|
3801
|
-
const keys = factFieldNames(decl).registryKeys;
|
|
3802
|
-
const collidingKey = keys.find((k) => owners.has(k));
|
|
3803
|
-
if (collidingKey !== void 0) {
|
|
3804
|
-
const owner = owners.get(collidingKey);
|
|
3805
|
-
if (owner === "built-in") {
|
|
3806
|
-
problems.push(`fact "${name}": exported field "${collidingKey}" collides with a built-in field`);
|
|
3807
|
-
} else if (owner === name) {
|
|
3808
|
-
problems.push(`fact "${name}": duplicate declaration (a fact named "${name}" is already declared)`);
|
|
3809
|
-
} else {
|
|
3810
|
-
problems.push(`fact "${name}": exported field "${collidingKey}" collides with fact "${owner}"`);
|
|
3811
|
-
}
|
|
3812
|
-
continue;
|
|
3813
|
-
}
|
|
3814
|
-
for (const key of keys) owners.set(key, name);
|
|
3815
|
-
}
|
|
3816
|
-
return problems;
|
|
3817
|
-
}
|
|
3818
3818
|
function serializeIntegrationConfig(integrations) {
|
|
3819
3819
|
const lines = [];
|
|
3820
3820
|
if (integrations.claudePluginDir) {
|
|
@@ -4894,7 +4894,6 @@ var init_config2 = __esm({
|
|
|
4894
4894
|
init_agents_schema();
|
|
4895
4895
|
init_slug();
|
|
4896
4896
|
init_fact_registry();
|
|
4897
|
-
init_query();
|
|
4898
4897
|
init_terminal_schema();
|
|
4899
4898
|
init_workspace_visibility_schema();
|
|
4900
4899
|
DEFAULT_DERIVE_CONFIG = {
|
|
@@ -7301,7 +7300,8 @@ function rowToSession(row) {
|
|
|
7301
7300
|
transcriptPath: row.transcript_path ?? null,
|
|
7302
7301
|
pid: row.pid ?? null,
|
|
7303
7302
|
pidStartedAt: row.pid_started_at ?? null,
|
|
7304
|
-
originalHeadSha: row.original_head_sha ?? null
|
|
7303
|
+
originalHeadSha: row.original_head_sha ?? null,
|
|
7304
|
+
updatedAt: row.updated_at ?? null
|
|
7305
7305
|
};
|
|
7306
7306
|
}
|
|
7307
7307
|
async function parseSessionsIndex(_projectDir, projectSlug) {
|
|
@@ -8765,24 +8765,28 @@ async function getStatusConfig() {
|
|
|
8765
8765
|
if (_cachedConfig) return _cachedConfig;
|
|
8766
8766
|
const config = await readConfig();
|
|
8767
8767
|
if (config.statuses) {
|
|
8768
|
+
const sc = config.statuses;
|
|
8769
|
+
const defaults = sc.statuses.length === 0 ? buildDefaultStatusConfig() : null;
|
|
8770
|
+
const effectiveStatuses = defaults ? defaults.statuses : sc.statuses;
|
|
8771
|
+
const effectiveOrder = defaults ? defaults.order : sc.order;
|
|
8768
8772
|
const terminalSet = new Set(
|
|
8769
|
-
|
|
8773
|
+
effectiveStatuses.filter((s) => s.terminal).map((s) => s.id)
|
|
8770
8774
|
);
|
|
8771
|
-
const hasCustomTransitions =
|
|
8772
|
-
const effectiveTransitions2 = hasCustomTransitions ?
|
|
8775
|
+
const hasCustomTransitions = sc.transitions.length > 0;
|
|
8776
|
+
const effectiveTransitions2 = hasCustomTransitions ? sc.transitions : Array.from(DEFAULT_TRANSITION_TABLE.entries()).map(([key, to]) => {
|
|
8773
8777
|
const [from, command] = key.split(":");
|
|
8774
8778
|
return { from, command, to };
|
|
8775
8779
|
});
|
|
8776
|
-
const accepted = acceptFactDeclarations(normalizeFactDeclarations(
|
|
8780
|
+
const accepted = acceptFactDeclarations(normalizeFactDeclarations(sc.facts ?? null));
|
|
8777
8781
|
_cachedConfig = {
|
|
8778
8782
|
custom: true,
|
|
8779
|
-
statuses:
|
|
8780
|
-
order:
|
|
8783
|
+
statuses: effectiveStatuses,
|
|
8784
|
+
order: effectiveOrder,
|
|
8781
8785
|
transitions: effectiveTransitions2,
|
|
8782
8786
|
transitionTable: buildTransitionTable(effectiveTransitions2),
|
|
8783
8787
|
terminalStatuses: terminalSet.size > 0 ? terminalSet : /* @__PURE__ */ new Set(["completed", "failed"]),
|
|
8784
|
-
derive:
|
|
8785
|
-
facts:
|
|
8788
|
+
derive: sc.derive ?? null,
|
|
8789
|
+
facts: sc.facts ?? null,
|
|
8786
8790
|
factDeclarations: accepted,
|
|
8787
8791
|
deriveRegistry: buildDeriveRegistry(accepted),
|
|
8788
8792
|
queryRegistry: buildQueryRegistry(accepted)
|
|
@@ -9946,7 +9950,7 @@ async function buildDerivedDetail(assignment, assignmentDir, projectDir) {
|
|
|
9946
9950
|
try {
|
|
9947
9951
|
const { computeFactsDetailed: computeFactsDetailed2 } = await Promise.resolve().then(() => (init_facts(), facts_exports));
|
|
9948
9952
|
const { deriveDimensions: deriveDimensions2 } = await Promise.resolve().then(() => (init_derive(), derive_exports));
|
|
9949
|
-
const { DEFAULT_DERIVE_CONFIG:
|
|
9953
|
+
const { DEFAULT_DERIVE_CONFIG: DEFAULT_DERIVE_CONFIG3 } = await Promise.resolve().then(() => (init_config2(), config_exports));
|
|
9950
9954
|
const { facts, attestations } = await computeFactsDetailed2({
|
|
9951
9955
|
assignmentDir,
|
|
9952
9956
|
frontmatter: {
|
|
@@ -9961,7 +9965,7 @@ async function buildDerivedDetail(assignment, assignmentDir, projectDir) {
|
|
|
9961
9965
|
});
|
|
9962
9966
|
const dims = deriveDimensions2({
|
|
9963
9967
|
facts,
|
|
9964
|
-
derive: config.derive ??
|
|
9968
|
+
derive: config.derive ?? DEFAULT_DERIVE_CONFIG3,
|
|
9965
9969
|
currentStatus: assignment.status,
|
|
9966
9970
|
terminalStatuses: config.terminalStatuses,
|
|
9967
9971
|
knownStatusIds: new Set(config.statuses.map((s) => s.id)),
|
|
@@ -13871,7 +13875,11 @@ var SORT_FIELDS = [
|
|
|
13871
13875
|
"assignee",
|
|
13872
13876
|
"dependencies",
|
|
13873
13877
|
"created",
|
|
13874
|
-
"updated"
|
|
13878
|
+
"updated",
|
|
13879
|
+
"started",
|
|
13880
|
+
"lastActivity",
|
|
13881
|
+
"projectName",
|
|
13882
|
+
"agentName"
|
|
13875
13883
|
];
|
|
13876
13884
|
var SORT_DIRECTIONS = ["asc", "desc"];
|
|
13877
13885
|
var DENSITIES = ["comfortable", "compact"];
|
|
@@ -13884,7 +13892,7 @@ var GROUPINGS = [
|
|
|
13884
13892
|
"project"
|
|
13885
13893
|
];
|
|
13886
13894
|
var ACTIVITIES = ["all", "stale", "fresh"];
|
|
13887
|
-
var DATE_RANGE_FIELDS = ["created", "updated"];
|
|
13895
|
+
var DATE_RANGE_FIELDS = ["created", "updated", "started"];
|
|
13888
13896
|
var DATE_RANGE_PRESETS = [
|
|
13889
13897
|
"last_24h",
|
|
13890
13898
|
"last_7d",
|
|
@@ -14133,6 +14141,7 @@ function makeSeededView(id, name, filterOverrides) {
|
|
|
14133
14141
|
id,
|
|
14134
14142
|
name,
|
|
14135
14143
|
workspace: null,
|
|
14144
|
+
entityType: "assignment",
|
|
14136
14145
|
config: {
|
|
14137
14146
|
viewMode: "list",
|
|
14138
14147
|
filters: { ...DEFAULT_FILTERS, ...filterOverrides },
|
|
@@ -14170,7 +14179,13 @@ function isWidgetConfig(value) {
|
|
|
14170
14179
|
if (obj.kind === "saved-view") {
|
|
14171
14180
|
return typeof obj.viewId === "string" && obj.viewId.length > 0;
|
|
14172
14181
|
}
|
|
14173
|
-
|
|
14182
|
+
if (obj.kind === "agent-sessions") {
|
|
14183
|
+
if (obj.viewId !== void 0) {
|
|
14184
|
+
return typeof obj.viewId === "string" && obj.viewId.length > 0;
|
|
14185
|
+
}
|
|
14186
|
+
return true;
|
|
14187
|
+
}
|
|
14188
|
+
return obj.kind === "inventories";
|
|
14174
14189
|
}
|
|
14175
14190
|
function isListSectionVisibility(value) {
|
|
14176
14191
|
if (!value || typeof value !== "object") return false;
|
|
@@ -14207,6 +14222,9 @@ function isSavedViewConfig(value) {
|
|
|
14207
14222
|
function isSavedView(value) {
|
|
14208
14223
|
if (!value || typeof value !== "object") return false;
|
|
14209
14224
|
const obj = value;
|
|
14225
|
+
if (obj.entityType !== void 0 && obj.entityType !== "assignment" && obj.entityType !== "session") {
|
|
14226
|
+
return false;
|
|
14227
|
+
}
|
|
14210
14228
|
return typeof obj.id === "string" && obj.id.length > 0 && typeof obj.name === "string" && (obj.workspace === null || typeof obj.workspace === "string") && isSavedViewConfig(obj.config) && typeof obj.createdAt === "string" && typeof obj.updatedAt === "string";
|
|
14211
14229
|
}
|
|
14212
14230
|
function isDashboardSlot(value) {
|
|
@@ -14301,6 +14319,8 @@ function createSavedView(file, input4, now = () => (/* @__PURE__ */ new Date()).
|
|
|
14301
14319
|
id: randomUUID2(),
|
|
14302
14320
|
name: input4.name,
|
|
14303
14321
|
workspace: input4.workspace,
|
|
14322
|
+
// Only persist entityType when explicitly a session view; absent === assignment.
|
|
14323
|
+
...input4.entityType === "session" ? { entityType: "session" } : {},
|
|
14304
14324
|
config: input4.config,
|
|
14305
14325
|
createdAt: ts,
|
|
14306
14326
|
updatedAt: ts
|
|
@@ -14399,12 +14419,16 @@ function validateCreateBody(body) {
|
|
|
14399
14419
|
if (!isSavedViewConfig(obj.config)) {
|
|
14400
14420
|
return { ok: false, error: "config must be a valid SavedViewConfig" };
|
|
14401
14421
|
}
|
|
14422
|
+
if (obj.entityType !== void 0 && obj.entityType !== "assignment" && obj.entityType !== "session") {
|
|
14423
|
+
return { ok: false, error: "entityType must be 'assignment' or 'session'" };
|
|
14424
|
+
}
|
|
14402
14425
|
return {
|
|
14403
14426
|
ok: true,
|
|
14404
14427
|
value: {
|
|
14405
14428
|
name: obj.name.trim(),
|
|
14406
14429
|
workspace: obj.workspace,
|
|
14407
|
-
config: obj.config
|
|
14430
|
+
config: obj.config,
|
|
14431
|
+
...obj.entityType !== void 0 ? { entityType: obj.entityType } : {}
|
|
14408
14432
|
}
|
|
14409
14433
|
};
|
|
14410
14434
|
}
|
|
@@ -19359,7 +19383,9 @@ function createWorkspaceVisibilityConfigRouter() {
|
|
|
19359
19383
|
|
|
19360
19384
|
// src/dashboard/api-status-config.ts
|
|
19361
19385
|
init_config2();
|
|
19386
|
+
init_fact_registry();
|
|
19362
19387
|
init_api();
|
|
19388
|
+
init_derive();
|
|
19363
19389
|
import { Router as Router9 } from "express";
|
|
19364
19390
|
|
|
19365
19391
|
// src/utils/status-config-resolution.ts
|
|
@@ -19767,7 +19793,8 @@ function createStatusConfigRouter(projectsDir2, assignmentsDir2) {
|
|
|
19767
19793
|
order: config.order,
|
|
19768
19794
|
transitions: config.transitions,
|
|
19769
19795
|
custom: config.custom,
|
|
19770
|
-
factDeclarations: config.factDeclarations
|
|
19796
|
+
factDeclarations: config.factDeclarations,
|
|
19797
|
+
rawFacts: config.facts ?? []
|
|
19771
19798
|
});
|
|
19772
19799
|
} catch (error) {
|
|
19773
19800
|
console.error("Error getting status config:", error);
|
|
@@ -19791,8 +19818,27 @@ function createStatusConfigRouter(projectsDir2, assignmentsDir2) {
|
|
|
19791
19818
|
});
|
|
19792
19819
|
router.post("/", async (req, res) => {
|
|
19793
19820
|
try {
|
|
19794
|
-
const {
|
|
19795
|
-
|
|
19821
|
+
const {
|
|
19822
|
+
statuses,
|
|
19823
|
+
order,
|
|
19824
|
+
transitions,
|
|
19825
|
+
facts: bodyFacts,
|
|
19826
|
+
factRemovalAcks,
|
|
19827
|
+
resolutions: rawResolutions
|
|
19828
|
+
} = req.body ?? {};
|
|
19829
|
+
const currentConfig = await getStatusConfig();
|
|
19830
|
+
const hasFacts = bodyFacts !== void 0;
|
|
19831
|
+
const hasStatuses = statuses !== void 0;
|
|
19832
|
+
const hasOrder = order !== void 0;
|
|
19833
|
+
const hasTransitions = transitions !== void 0;
|
|
19834
|
+
let effectiveStatuses = statuses;
|
|
19835
|
+
let effectiveOrder = order;
|
|
19836
|
+
let effectiveTransitions2 = transitions;
|
|
19837
|
+
if (hasFacts && !hasStatuses && !hasOrder && !hasTransitions) {
|
|
19838
|
+
effectiveStatuses = currentConfig.statuses;
|
|
19839
|
+
effectiveOrder = currentConfig.order;
|
|
19840
|
+
effectiveTransitions2 = currentConfig.transitions;
|
|
19841
|
+
} else if (!Array.isArray(effectiveStatuses) || !Array.isArray(effectiveOrder) || !Array.isArray(effectiveTransitions2)) {
|
|
19796
19842
|
res.status(400).json({ error: "malformed-statuses", message: "Request body must include statuses, order, and transitions arrays" });
|
|
19797
19843
|
return;
|
|
19798
19844
|
}
|
|
@@ -19806,10 +19852,9 @@ function createStatusConfigRouter(projectsDir2, assignmentsDir2) {
|
|
|
19806
19852
|
return;
|
|
19807
19853
|
}
|
|
19808
19854
|
const resolutions = parsed.resolutions;
|
|
19809
|
-
const currentConfig = await getStatusConfig();
|
|
19810
19855
|
const oldIds = new Set(currentConfig.statuses.map((s) => s.id));
|
|
19811
19856
|
const newIds = /* @__PURE__ */ new Set();
|
|
19812
|
-
for (const s of
|
|
19857
|
+
for (const s of effectiveStatuses) {
|
|
19813
19858
|
if (s && typeof s === "object" && isString(s.id)) {
|
|
19814
19859
|
newIds.add(s.id);
|
|
19815
19860
|
}
|
|
@@ -19890,13 +19935,83 @@ function createStatusConfigRouter(projectsDir2, assignmentsDir2) {
|
|
|
19890
19935
|
}
|
|
19891
19936
|
throw err2;
|
|
19892
19937
|
}
|
|
19938
|
+
let factsToWrite = currentConfig.facts ?? null;
|
|
19939
|
+
if (hasFacts) {
|
|
19940
|
+
const shapedFacts = [];
|
|
19941
|
+
if (!Array.isArray(bodyFacts)) {
|
|
19942
|
+
res.status(400).json({ error: "malformed-facts", message: "facts must be an array" });
|
|
19943
|
+
return;
|
|
19944
|
+
}
|
|
19945
|
+
for (let i = 0; i < bodyFacts.length; i++) {
|
|
19946
|
+
const row = bodyFacts[i];
|
|
19947
|
+
if (!row || typeof row !== "object") {
|
|
19948
|
+
res.status(400).json({ error: "malformed-facts", message: `facts[${i}] must be an object` });
|
|
19949
|
+
return;
|
|
19950
|
+
}
|
|
19951
|
+
const name = row.name;
|
|
19952
|
+
const type = row.type;
|
|
19953
|
+
if (typeof name !== "string" || typeof type !== "string") {
|
|
19954
|
+
res.status(400).json({ error: "malformed-facts", message: `facts[${i}] must have name and type strings` });
|
|
19955
|
+
return;
|
|
19956
|
+
}
|
|
19957
|
+
const binds = row.binds;
|
|
19958
|
+
const normalizedBinds = binds === void 0 ? null : binds === null ? null : typeof binds === "string" ? binds : null;
|
|
19959
|
+
shapedFacts.push({ name, type, binds: normalizedBinds });
|
|
19960
|
+
}
|
|
19961
|
+
const problems = validateFactDeclarations(shapedFacts);
|
|
19962
|
+
if (problems.length > 0) {
|
|
19963
|
+
res.status(400).json({ error: "invalid-facts", problems });
|
|
19964
|
+
return;
|
|
19965
|
+
}
|
|
19966
|
+
const currentNames = new Set((currentConfig.facts ?? []).map((f) => f.name));
|
|
19967
|
+
const incomingNames = new Set(shapedFacts.map((f) => f.name));
|
|
19968
|
+
const removedNames = [];
|
|
19969
|
+
for (const name of currentNames) {
|
|
19970
|
+
if (!incomingNames.has(name)) removedNames.push(name);
|
|
19971
|
+
}
|
|
19972
|
+
const acks = new Set(Array.isArray(factRemovalAcks) ? factRemovalAcks.map((x) => String(x)) : []);
|
|
19973
|
+
const unresolvedRefs = [];
|
|
19974
|
+
const deriveConfig = currentConfig.derive ?? null;
|
|
19975
|
+
if (deriveConfig !== null && removedNames.length > 0) {
|
|
19976
|
+
const acceptedAll = acceptFactDeclarations(normalizeFactDeclarations(currentConfig.facts));
|
|
19977
|
+
const fullRegistry = buildDeriveRegistry(acceptedAll);
|
|
19978
|
+
for (const removedName of removedNames) {
|
|
19979
|
+
if (acks.has(removedName)) continue;
|
|
19980
|
+
const acceptedWithout = acceptedAll.filter((d) => d.name !== removedName);
|
|
19981
|
+
const withoutRegistry = buildDeriveRegistry(acceptedWithout);
|
|
19982
|
+
for (let i = 0; i < deriveConfig.phaseLadder.length; i++) {
|
|
19983
|
+
const rung = deriveConfig.phaseLadder[i];
|
|
19984
|
+
if (rung.when === "*") continue;
|
|
19985
|
+
const before = validateDeriveCondition(rung.when, fullRegistry);
|
|
19986
|
+
const after = validateDeriveCondition(rung.when, withoutRegistry);
|
|
19987
|
+
if (before === null && after !== null) {
|
|
19988
|
+
unresolvedRefs.push({ factName: removedName, location: `phaseLadder[${i}]`, when: rung.when });
|
|
19989
|
+
}
|
|
19990
|
+
}
|
|
19991
|
+
for (let i = 0; i < deriveConfig.disposition.length; i++) {
|
|
19992
|
+
const rule = deriveConfig.disposition[i];
|
|
19993
|
+
if (rule.when === null) continue;
|
|
19994
|
+
const before = validateDeriveCondition(rule.when, fullRegistry);
|
|
19995
|
+
const after = validateDeriveCondition(rule.when, withoutRegistry);
|
|
19996
|
+
if (before === null && after !== null) {
|
|
19997
|
+
unresolvedRefs.push({ factName: removedName, location: `disposition[${i}]`, when: rule.when });
|
|
19998
|
+
}
|
|
19999
|
+
}
|
|
20000
|
+
}
|
|
20001
|
+
}
|
|
20002
|
+
if (unresolvedRefs.length > 0) {
|
|
20003
|
+
res.status(409).json({ error: "unresolved-fact-references", references: unresolvedRefs });
|
|
20004
|
+
return;
|
|
20005
|
+
}
|
|
20006
|
+
factsToWrite = shapedFacts;
|
|
20007
|
+
}
|
|
19893
20008
|
try {
|
|
19894
20009
|
await writeStatusConfig({
|
|
19895
|
-
statuses,
|
|
19896
|
-
order,
|
|
19897
|
-
transitions,
|
|
20010
|
+
statuses: effectiveStatuses,
|
|
20011
|
+
order: effectiveOrder,
|
|
20012
|
+
transitions: effectiveTransitions2,
|
|
19898
20013
|
derive: currentConfig.derive ?? null,
|
|
19899
|
-
facts:
|
|
20014
|
+
facts: factsToWrite
|
|
19900
20015
|
});
|
|
19901
20016
|
} catch (err2) {
|
|
19902
20017
|
console.error("Error saving status config after applying resolutions:", err2);
|
|
@@ -38367,7 +38482,9 @@ var KNOWN_FILTER_KEYS = /* @__PURE__ */ new Set([
|
|
|
38367
38482
|
"activity",
|
|
38368
38483
|
"dateRange",
|
|
38369
38484
|
"search",
|
|
38370
|
-
"query"
|
|
38485
|
+
"query",
|
|
38486
|
+
"sessionStatus",
|
|
38487
|
+
"agent"
|
|
38371
38488
|
]);
|
|
38372
38489
|
function preserveUnknownFilterKeys(existing, built) {
|
|
38373
38490
|
const out = {};
|
|
@@ -38383,6 +38500,9 @@ function mergeUpdatedConfig(existing, built, visibility) {
|
|
|
38383
38500
|
filters: preserveUnknownFilterKeys(existing.filters, built.filters),
|
|
38384
38501
|
sortField: built.sortField,
|
|
38385
38502
|
sortDirection: built.sortDirection,
|
|
38503
|
+
// `limit` is rebuilt from `built` (session views); assignment edits carry
|
|
38504
|
+
// undefined here, which serializes away — so this can't leak a stale limit.
|
|
38505
|
+
limit: built.limit,
|
|
38386
38506
|
listSectionVisibility: { collapsed: [...visibility.listSectionVisibility.collapsed] },
|
|
38387
38507
|
kanbanColumnVisibility: { hidden: [...visibility.kanbanColumnVisibility.hidden] },
|
|
38388
38508
|
tableColumnVisibility: { hidden: [...visibility.tableColumnVisibility.hidden] }
|
|
@@ -38407,6 +38527,10 @@ function minimizeFilters(filters, forcedProject) {
|
|
|
38407
38527
|
if (project.length) minimal.project = project;
|
|
38408
38528
|
}
|
|
38409
38529
|
if (filters.activity && filters.activity !== "all") minimal.activity = filters.activity;
|
|
38530
|
+
const sessionStatus = toFilterValues(filters.sessionStatus);
|
|
38531
|
+
if (sessionStatus.length) minimal.sessionStatus = sessionStatus;
|
|
38532
|
+
const agent = toFilterValues(filters.agent);
|
|
38533
|
+
if (agent.length) minimal.agent = agent;
|
|
38410
38534
|
if (filters.dateRange) minimal.dateRange = filters.dateRange;
|
|
38411
38535
|
const search = filters.search?.trim();
|
|
38412
38536
|
if (search) minimal.search = search;
|