trackops 2.0.6 → 2.1.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/README.md +295 -701
- package/bin/trackops.js +24 -16
- package/lib/config.js +265 -58
- package/lib/control.js +830 -292
- package/lib/init.js +46 -16
- package/lib/opera-bootstrap.js +85 -45
- package/lib/opera-phase-dod.js +485 -0
- package/lib/opera.js +8 -5
- package/lib/plans.js +1329 -0
- package/lib/quality-assert.js +49 -0
- package/lib/quality.js +1759 -0
- package/lib/release.js +18 -11
- package/lib/server.js +504 -192
- package/locales/en.json +249 -15
- package/locales/es.json +249 -15
- package/package.json +6 -5
- package/scripts/quality-unit-tests.js +130 -0
- package/scripts/smoke-tests.js +357 -57
- package/skills/trackops/skill.json +29 -29
- package/templates/skills/opera-quality-guard/SKILL.md +26 -0
- package/templates/skills/opera-quality-guard/locales/en/SKILL.md +26 -0
- package/templates/skills/opera-skill/SKILL.md +8 -0
- package/templates/skills/opera-skill/locales/en/SKILL.md +8 -0
- package/ui/js/api.js +93 -26
- package/ui/js/app.js +13 -7
- package/ui/js/filters.js +49 -29
- package/ui/js/time-tracker.js +41 -28
- package/ui/js/views/board.js +22 -14
- package/ui/js/views/dashboard.js +206 -49
- package/ui/js/views/execution.js +7 -3
- package/ui/js/views/plans.js +284 -0
- package/ui/js/views/scrum.js +25 -13
- package/ui/js/views/sidebar.js +9 -8
- package/ui/js/views/tasks.js +238 -134
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
function assertControlInvariants(control) {
|
|
4
|
+
if (!control || typeof control !== "object") {
|
|
5
|
+
throw new Error("TRACKOPS_ASSERT: control state must be an object.");
|
|
6
|
+
}
|
|
7
|
+
if (!Array.isArray(control.tasks)) {
|
|
8
|
+
throw new Error("TRACKOPS_ASSERT: control.tasks must be an array.");
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const ids = new Set();
|
|
12
|
+
const duplicates = new Set();
|
|
13
|
+
for (const task of control.tasks) {
|
|
14
|
+
const id = String(task?.id || "").trim();
|
|
15
|
+
if (!id) {
|
|
16
|
+
throw new Error("TRACKOPS_ASSERT: every task must have a non-empty id.");
|
|
17
|
+
}
|
|
18
|
+
if (ids.has(id)) duplicates.add(id);
|
|
19
|
+
ids.add(id);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (duplicates.size) {
|
|
23
|
+
throw new Error(`TRACKOPS_ASSERT: duplicate task ids detected: ${[...duplicates].join(", ")}`);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
for (const task of control.tasks) {
|
|
27
|
+
const id = String(task.id || "").trim();
|
|
28
|
+
const parentId = String(task.parentId || "").trim();
|
|
29
|
+
if (parentId) {
|
|
30
|
+
if (parentId === id) {
|
|
31
|
+
throw new Error(`TRACKOPS_ASSERT: task '${id}' cannot be its own parent.`);
|
|
32
|
+
}
|
|
33
|
+
if (!ids.has(parentId)) {
|
|
34
|
+
throw new Error(`TRACKOPS_ASSERT: task '${id}' references missing parent '${parentId}'.`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
for (const dep of Array.isArray(task.dependsOn) ? task.dependsOn : []) {
|
|
38
|
+
const depId = String(dep || "").trim();
|
|
39
|
+
if (!depId) continue;
|
|
40
|
+
if (depId === id) {
|
|
41
|
+
throw new Error(`TRACKOPS_ASSERT: task '${id}' cannot depend on itself.`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
module.exports = {
|
|
48
|
+
assertControlInvariants,
|
|
49
|
+
};
|