syntaur 0.47.0 → 0.49.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-DgR0_P-o.js → _basePickBy-D_1PqV49.js} +1 -1
- package/dashboard/dist/assets/{_baseUniq-C8_Ych09.js → _baseUniq-Go3lJYWk.js} +1 -1
- package/dashboard/dist/assets/{arc-yMHz4vGa.js → arc-CPkf0K8o.js} +1 -1
- package/dashboard/dist/assets/{architectureDiagram-2XIMDMQ5-ColWcH3P.js → architectureDiagram-2XIMDMQ5-D-YQc-ni.js} +1 -1
- package/dashboard/dist/assets/{blockDiagram-WCTKOSBZ-Bo8Npvfq.js → blockDiagram-WCTKOSBZ-BYKjgbgS.js} +1 -1
- package/dashboard/dist/assets/{c4Diagram-IC4MRINW-B2ky8AT7.js → c4Diagram-IC4MRINW-DL0q4c_7.js} +1 -1
- package/dashboard/dist/assets/channel-BogPsJQf.js +1 -0
- package/dashboard/dist/assets/{chunk-4BX2VUAB-CyF6Z6dx.js → chunk-4BX2VUAB-Dz3hphvh.js} +1 -1
- package/dashboard/dist/assets/{chunk-55IACEB6-BJOEnwNN.js → chunk-55IACEB6-KkMi7-rO.js} +1 -1
- package/dashboard/dist/assets/{chunk-FMBD7UC4-D3siQyQ4.js → chunk-FMBD7UC4-C6i7PgE-.js} +1 -1
- package/dashboard/dist/assets/{chunk-JSJVCQXG-DKGuxEMf.js → chunk-JSJVCQXG-D9nWD3SH.js} +1 -1
- package/dashboard/dist/assets/{chunk-KX2RTZJC-CNIWWO2F.js → chunk-KX2RTZJC-C-pz_QfY.js} +1 -1
- package/dashboard/dist/assets/{chunk-NQ4KR5QH-DXt05c7h.js → chunk-NQ4KR5QH-m21dA_AB.js} +1 -1
- package/dashboard/dist/assets/{chunk-QZHKN3VN-CM63uYnf.js → chunk-QZHKN3VN-BTYD7vUi.js} +1 -1
- package/dashboard/dist/assets/{chunk-WL4C6EOR-Dqvl_14m.js → chunk-WL4C6EOR-D_92eLJ7.js} +1 -1
- package/dashboard/dist/assets/classDiagram-VBA2DB6C-LFy25hGC.js +1 -0
- package/dashboard/dist/assets/classDiagram-v2-RAHNMMFH-LFy25hGC.js +1 -0
- package/dashboard/dist/assets/clone-B2jJrmVo.js +1 -0
- package/dashboard/dist/assets/{cose-bilkent-S5V4N54A-WBLtT1w9.js → cose-bilkent-S5V4N54A-xG37nIJ5.js} +1 -1
- package/dashboard/dist/assets/{dagre-KLK3FWXG-DIdQdwa7.js → dagre-KLK3FWXG-BmMnqFf5.js} +1 -1
- package/dashboard/dist/assets/{diagram-E7M64L7V-BEH6P_Sk.js → diagram-E7M64L7V-NKwCHorn.js} +1 -1
- package/dashboard/dist/assets/{diagram-IFDJBPK2-BuhxBcSy.js → diagram-IFDJBPK2-RFbM55z9.js} +1 -1
- package/dashboard/dist/assets/{diagram-P4PSJMXO-DPSNVVzN.js → diagram-P4PSJMXO-DFATQN63.js} +1 -1
- package/dashboard/dist/assets/{erDiagram-INFDFZHY-DYJb_rF5.js → erDiagram-INFDFZHY-CnkbUfYo.js} +1 -1
- package/dashboard/dist/assets/{flowDiagram-PKNHOUZH-B9_8BI26.js → flowDiagram-PKNHOUZH-C2bCpv_b.js} +1 -1
- package/dashboard/dist/assets/{ganttDiagram-A5KZAMGK-Bsg3QOhs.js → ganttDiagram-A5KZAMGK-Cyz3i9ox.js} +1 -1
- package/dashboard/dist/assets/{gitGraphDiagram-K3NZZRJ6-Cf5G9x_K.js → gitGraphDiagram-K3NZZRJ6-DNSJOJPu.js} +1 -1
- package/dashboard/dist/assets/{graph-DyXfcrIH.js → graph-B0uvMYEt.js} +1 -1
- package/dashboard/dist/assets/index-J9J1LmFz.js +567 -0
- package/dashboard/dist/assets/index-hXP7kHLF.css +1 -0
- package/dashboard/dist/assets/{infoDiagram-LFFYTUFH-Bu1zlXs2.js → infoDiagram-LFFYTUFH-CIAGOhnc.js} +1 -1
- package/dashboard/dist/assets/{ishikawaDiagram-PHBUUO56-fb8C-XRT.js → ishikawaDiagram-PHBUUO56-Cz1e1z95.js} +1 -1
- package/dashboard/dist/assets/{journeyDiagram-4ABVD52K-smlBWs2O.js → journeyDiagram-4ABVD52K-DQpnaGS3.js} +1 -1
- package/dashboard/dist/assets/{kanban-definition-K7BYSVSG-Bz1AxFRE.js → kanban-definition-K7BYSVSG-ctedqNYC.js} +1 -1
- package/dashboard/dist/assets/{layout-VsTD3onG.js → layout-DB-MZUE7.js} +1 -1
- package/dashboard/dist/assets/{linear-CE8xncGu.js → linear-ChyfHemL.js} +1 -1
- package/dashboard/dist/assets/{mermaid.core-C0KQpDyW.js → mermaid.core-B7D9g8Z0.js} +4 -4
- package/dashboard/dist/assets/{mindmap-definition-YRQLILUH-SRE5Immj.js → mindmap-definition-YRQLILUH-BBwO3Cx_.js} +1 -1
- package/dashboard/dist/assets/{pieDiagram-SKSYHLDU-CaZ_aCcD.js → pieDiagram-SKSYHLDU-D5cgYxWS.js} +1 -1
- package/dashboard/dist/assets/{quadrantDiagram-337W2JSQ-Dd6MIruu.js → quadrantDiagram-337W2JSQ-D1PRaNvQ.js} +1 -1
- package/dashboard/dist/assets/{requirementDiagram-Z7DCOOCP-BBXvP53l.js → requirementDiagram-Z7DCOOCP-DSPKmecF.js} +1 -1
- package/dashboard/dist/assets/{sankeyDiagram-WA2Y5GQK-DnS1SMIm.js → sankeyDiagram-WA2Y5GQK-qoBrVPPJ.js} +1 -1
- package/dashboard/dist/assets/{sequenceDiagram-2WXFIKYE-CLHJ1Uhx.js → sequenceDiagram-2WXFIKYE-COHgbUzd.js} +1 -1
- package/dashboard/dist/assets/{stateDiagram-RAJIS63D-B6vrAeYw.js → stateDiagram-RAJIS63D-D7o2ec5P.js} +1 -1
- package/dashboard/dist/assets/stateDiagram-v2-FVOUBMTO-Bn85KIR5.js +1 -0
- package/dashboard/dist/assets/{timeline-definition-YZTLITO2-BlHwGfnL.js → timeline-definition-YZTLITO2-0_qvF5FF.js} +1 -1
- package/dashboard/dist/assets/{treemap-KZPCXAKY-D9kOGUYR.js → treemap-KZPCXAKY-DrWRWtnJ.js} +1 -1
- package/dashboard/dist/assets/{vennDiagram-LZ73GAT5-BpQgeveT.js → vennDiagram-LZ73GAT5-Chnf9HfQ.js} +1 -1
- package/dashboard/dist/assets/{xychartDiagram-JWTSCODW-DRch79fE.js → xychartDiagram-JWTSCODW-DZaMVdVS.js} +1 -1
- package/dashboard/dist/index.html +2 -2
- package/dist/dashboard/server.js +162 -68
- package/dist/dashboard/server.js.map +1 -1
- package/dist/index.js +162 -68
- package/dist/index.js.map +1 -1
- package/dist/launch/index.d.ts +25 -12
- package/dist/launch/index.js +60 -57
- 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-CUTEvTdk.js +0 -1
- package/dashboard/dist/assets/classDiagram-VBA2DB6C-Bkoc7orC.js +0 -1
- package/dashboard/dist/assets/classDiagram-v2-RAHNMMFH-Bkoc7orC.js +0 -1
- package/dashboard/dist/assets/clone-CltBg7cH.js +0 -1
- package/dashboard/dist/assets/index-C3kYxhbQ.js +0 -567
- package/dashboard/dist/assets/index-DKr21dk8.css +0 -1
- package/dashboard/dist/assets/stateDiagram-v2-FVOUBMTO-BeqNZKbk.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 = {
|
|
@@ -8766,24 +8765,28 @@ async function getStatusConfig() {
|
|
|
8766
8765
|
if (_cachedConfig) return _cachedConfig;
|
|
8767
8766
|
const config = await readConfig();
|
|
8768
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;
|
|
8769
8772
|
const terminalSet = new Set(
|
|
8770
|
-
|
|
8773
|
+
effectiveStatuses.filter((s) => s.terminal).map((s) => s.id)
|
|
8771
8774
|
);
|
|
8772
|
-
const hasCustomTransitions =
|
|
8773
|
-
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]) => {
|
|
8774
8777
|
const [from, command] = key.split(":");
|
|
8775
8778
|
return { from, command, to };
|
|
8776
8779
|
});
|
|
8777
|
-
const accepted = acceptFactDeclarations(normalizeFactDeclarations(
|
|
8780
|
+
const accepted = acceptFactDeclarations(normalizeFactDeclarations(sc.facts ?? null));
|
|
8778
8781
|
_cachedConfig = {
|
|
8779
8782
|
custom: true,
|
|
8780
|
-
statuses:
|
|
8781
|
-
order:
|
|
8783
|
+
statuses: effectiveStatuses,
|
|
8784
|
+
order: effectiveOrder,
|
|
8782
8785
|
transitions: effectiveTransitions2,
|
|
8783
8786
|
transitionTable: buildTransitionTable(effectiveTransitions2),
|
|
8784
8787
|
terminalStatuses: terminalSet.size > 0 ? terminalSet : /* @__PURE__ */ new Set(["completed", "failed"]),
|
|
8785
|
-
derive:
|
|
8786
|
-
facts:
|
|
8788
|
+
derive: sc.derive ?? null,
|
|
8789
|
+
facts: sc.facts ?? null,
|
|
8787
8790
|
factDeclarations: accepted,
|
|
8788
8791
|
deriveRegistry: buildDeriveRegistry(accepted),
|
|
8789
8792
|
queryRegistry: buildQueryRegistry(accepted)
|
|
@@ -9947,7 +9950,7 @@ async function buildDerivedDetail(assignment, assignmentDir, projectDir) {
|
|
|
9947
9950
|
try {
|
|
9948
9951
|
const { computeFactsDetailed: computeFactsDetailed2 } = await Promise.resolve().then(() => (init_facts(), facts_exports));
|
|
9949
9952
|
const { deriveDimensions: deriveDimensions2 } = await Promise.resolve().then(() => (init_derive(), derive_exports));
|
|
9950
|
-
const { DEFAULT_DERIVE_CONFIG:
|
|
9953
|
+
const { DEFAULT_DERIVE_CONFIG: DEFAULT_DERIVE_CONFIG3 } = await Promise.resolve().then(() => (init_config2(), config_exports));
|
|
9951
9954
|
const { facts, attestations } = await computeFactsDetailed2({
|
|
9952
9955
|
assignmentDir,
|
|
9953
9956
|
frontmatter: {
|
|
@@ -9962,7 +9965,7 @@ async function buildDerivedDetail(assignment, assignmentDir, projectDir) {
|
|
|
9962
9965
|
});
|
|
9963
9966
|
const dims = deriveDimensions2({
|
|
9964
9967
|
facts,
|
|
9965
|
-
derive: config.derive ??
|
|
9968
|
+
derive: config.derive ?? DEFAULT_DERIVE_CONFIG3,
|
|
9966
9969
|
currentStatus: assignment.status,
|
|
9967
9970
|
terminalStatuses: config.terminalStatuses,
|
|
9968
9971
|
knownStatusIds: new Set(config.statuses.map((s) => s.id)),
|
|
@@ -19380,7 +19383,9 @@ function createWorkspaceVisibilityConfigRouter() {
|
|
|
19380
19383
|
|
|
19381
19384
|
// src/dashboard/api-status-config.ts
|
|
19382
19385
|
init_config2();
|
|
19386
|
+
init_fact_registry();
|
|
19383
19387
|
init_api();
|
|
19388
|
+
init_derive();
|
|
19384
19389
|
import { Router as Router9 } from "express";
|
|
19385
19390
|
|
|
19386
19391
|
// src/utils/status-config-resolution.ts
|
|
@@ -19788,7 +19793,8 @@ function createStatusConfigRouter(projectsDir2, assignmentsDir2) {
|
|
|
19788
19793
|
order: config.order,
|
|
19789
19794
|
transitions: config.transitions,
|
|
19790
19795
|
custom: config.custom,
|
|
19791
|
-
factDeclarations: config.factDeclarations
|
|
19796
|
+
factDeclarations: config.factDeclarations,
|
|
19797
|
+
rawFacts: config.facts ?? []
|
|
19792
19798
|
});
|
|
19793
19799
|
} catch (error) {
|
|
19794
19800
|
console.error("Error getting status config:", error);
|
|
@@ -19812,8 +19818,27 @@ function createStatusConfigRouter(projectsDir2, assignmentsDir2) {
|
|
|
19812
19818
|
});
|
|
19813
19819
|
router.post("/", async (req, res) => {
|
|
19814
19820
|
try {
|
|
19815
|
-
const {
|
|
19816
|
-
|
|
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)) {
|
|
19817
19842
|
res.status(400).json({ error: "malformed-statuses", message: "Request body must include statuses, order, and transitions arrays" });
|
|
19818
19843
|
return;
|
|
19819
19844
|
}
|
|
@@ -19827,10 +19852,9 @@ function createStatusConfigRouter(projectsDir2, assignmentsDir2) {
|
|
|
19827
19852
|
return;
|
|
19828
19853
|
}
|
|
19829
19854
|
const resolutions = parsed.resolutions;
|
|
19830
|
-
const currentConfig = await getStatusConfig();
|
|
19831
19855
|
const oldIds = new Set(currentConfig.statuses.map((s) => s.id));
|
|
19832
19856
|
const newIds = /* @__PURE__ */ new Set();
|
|
19833
|
-
for (const s of
|
|
19857
|
+
for (const s of effectiveStatuses) {
|
|
19834
19858
|
if (s && typeof s === "object" && isString(s.id)) {
|
|
19835
19859
|
newIds.add(s.id);
|
|
19836
19860
|
}
|
|
@@ -19911,13 +19935,83 @@ function createStatusConfigRouter(projectsDir2, assignmentsDir2) {
|
|
|
19911
19935
|
}
|
|
19912
19936
|
throw err2;
|
|
19913
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
|
+
}
|
|
19914
20008
|
try {
|
|
19915
20009
|
await writeStatusConfig({
|
|
19916
|
-
statuses,
|
|
19917
|
-
order,
|
|
19918
|
-
transitions,
|
|
20010
|
+
statuses: effectiveStatuses,
|
|
20011
|
+
order: effectiveOrder,
|
|
20012
|
+
transitions: effectiveTransitions2,
|
|
19919
20013
|
derive: currentConfig.derive ?? null,
|
|
19920
|
-
facts:
|
|
20014
|
+
facts: factsToWrite
|
|
19921
20015
|
});
|
|
19922
20016
|
} catch (err2) {
|
|
19923
20017
|
console.error("Error saving status config after applying resolutions:", err2);
|