trackops 2.0.3 → 2.0.5

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.
Files changed (103) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +695 -402
  3. package/bin/trackops.js +116 -116
  4. package/lib/config.js +326 -326
  5. package/lib/control.js +208 -208
  6. package/lib/env.js +244 -244
  7. package/lib/init.js +325 -325
  8. package/lib/locale.js +24 -0
  9. package/lib/opera-bootstrap.js +941 -874
  10. package/lib/opera.js +494 -477
  11. package/lib/preferences.js +74 -74
  12. package/lib/registry.js +214 -196
  13. package/lib/release.js +56 -56
  14. package/lib/runtime-state.js +144 -144
  15. package/lib/server.js +312 -207
  16. package/lib/skills.js +74 -57
  17. package/lib/workspace.js +260 -260
  18. package/locales/en.json +192 -166
  19. package/locales/es.json +192 -166
  20. package/package.json +61 -58
  21. package/scripts/postinstall-locale.js +21 -21
  22. package/scripts/skills-marketplace-smoke.js +124 -124
  23. package/scripts/smoke-tests.js +558 -554
  24. package/scripts/sync-skill-version.js +21 -21
  25. package/scripts/validate-skill.js +103 -103
  26. package/skills/trackops/SKILL.md +126 -122
  27. package/skills/trackops/agents/openai.yaml +7 -7
  28. package/skills/trackops/locales/en/SKILL.md +126 -122
  29. package/skills/trackops/locales/en/references/activation.md +94 -75
  30. package/skills/trackops/locales/en/references/troubleshooting.md +73 -55
  31. package/skills/trackops/locales/en/references/workflow.md +55 -32
  32. package/skills/trackops/references/activation.md +94 -75
  33. package/skills/trackops/references/troubleshooting.md +73 -55
  34. package/skills/trackops/references/workflow.md +55 -32
  35. package/skills/trackops/skill.json +29 -29
  36. package/templates/hooks/post-checkout +2 -2
  37. package/templates/hooks/post-commit +2 -2
  38. package/templates/hooks/post-merge +2 -2
  39. package/templates/opera/agent.md +28 -27
  40. package/templates/opera/architecture/dependency-graph.md +24 -24
  41. package/templates/opera/architecture/runtime-automation.md +24 -24
  42. package/templates/opera/architecture/runtime-operations.md +34 -34
  43. package/templates/opera/en/agent.md +22 -21
  44. package/templates/opera/en/architecture/dependency-graph.md +24 -24
  45. package/templates/opera/en/architecture/runtime-automation.md +24 -24
  46. package/templates/opera/en/architecture/runtime-operations.md +34 -34
  47. package/templates/opera/en/reviews/delivery-audit.md +18 -18
  48. package/templates/opera/en/reviews/integration-audit.md +18 -18
  49. package/templates/opera/en/router.md +24 -19
  50. package/templates/opera/references/autonomy-and-recovery.md +117 -117
  51. package/templates/opera/references/opera-cycle.md +193 -193
  52. package/templates/opera/registry.md +28 -28
  53. package/templates/opera/reviews/delivery-audit.md +18 -18
  54. package/templates/opera/reviews/integration-audit.md +18 -18
  55. package/templates/opera/router.md +54 -49
  56. package/templates/skills/changelog-updater/SKILL.md +69 -69
  57. package/templates/skills/commiter/SKILL.md +99 -99
  58. package/templates/skills/opera-contract-auditor/SKILL.md +38 -38
  59. package/templates/skills/opera-contract-auditor/locales/en/SKILL.md +38 -38
  60. package/templates/skills/opera-policy-guard/SKILL.md +26 -26
  61. package/templates/skills/opera-policy-guard/locales/en/SKILL.md +26 -26
  62. package/templates/skills/opera-skill/SKILL.md +279 -0
  63. package/templates/skills/opera-skill/locales/en/SKILL.md +279 -0
  64. package/templates/skills/opera-skill/locales/en/references/phase-dod.md +138 -0
  65. package/templates/skills/opera-skill/references/phase-dod.md +138 -0
  66. package/templates/skills/project-starter-skill/SKILL.md +150 -131
  67. package/templates/skills/project-starter-skill/locales/en/SKILL.md +143 -105
  68. package/templates/skills/project-starter-skill/references/opera-cycle.md +195 -193
  69. package/ui/css/base.css +284 -266
  70. package/ui/css/charts.css +425 -327
  71. package/ui/css/components.css +1107 -570
  72. package/ui/css/onboarding.css +133 -0
  73. package/ui/css/panels.css +345 -406
  74. package/ui/css/terminal.css +125 -0
  75. package/ui/css/timeline.css +58 -0
  76. package/ui/css/tokens.css +284 -227
  77. package/ui/favicon.svg +5 -5
  78. package/ui/index.html +99 -96
  79. package/ui/js/api.js +49 -13
  80. package/ui/js/app.js +28 -32
  81. package/ui/js/charts.js +526 -0
  82. package/ui/js/console-logger.js +172 -172
  83. package/ui/js/filters.js +247 -0
  84. package/ui/js/icons.js +129 -104
  85. package/ui/js/keyboard.js +229 -0
  86. package/ui/js/onboarding.js +33 -42
  87. package/ui/js/router.js +142 -125
  88. package/ui/js/theme.js +100 -100
  89. package/ui/js/time-tracker.js +248 -248
  90. package/ui/js/views/board.js +84 -114
  91. package/ui/js/views/dashboard.js +870 -0
  92. package/ui/js/views/flash.js +47 -47
  93. package/ui/js/views/projects.js +745 -0
  94. package/ui/js/views/scrum.js +476 -0
  95. package/ui/js/views/settings.js +153 -203
  96. package/ui/js/views/sidebar.js +37 -31
  97. package/ui/js/views/tasks.js +218 -101
  98. package/ui/js/views/timeline.js +265 -0
  99. package/ui/js/views/topbar.js +94 -107
  100. package/ui/app.js +0 -950
  101. package/ui/js/views/insights.js +0 -340
  102. package/ui/js/views/overview.js +0 -369
  103. package/ui/styles.css +0 -688
package/lib/skills.js CHANGED
@@ -8,6 +8,14 @@ const { t, setLocale } = require("./i18n");
8
8
  const { resolveSkillFile } = require("./resources");
9
9
 
10
10
  const SKILLS_TEMPLATES_DIR = path.join(__dirname, "..", "templates", "skills");
11
+ const INSTALLED_SKILL_PRIORITY = [
12
+ "opera-skill",
13
+ "project-starter-skill",
14
+ "opera-contract-auditor",
15
+ "opera-policy-guard",
16
+ "commiter",
17
+ "changelog-updater",
18
+ ];
11
19
 
12
20
  function copyDirRecursive(src, dest) {
13
21
  fs.mkdirSync(dest, { recursive: true });
@@ -22,9 +30,9 @@ function copyDirRecursive(src, dest) {
22
30
  }
23
31
  }
24
32
 
25
- function parseFrontmatter(content) {
26
- const match = content.match(/^---\s*\n([\s\S]*?)\n---/);
27
- if (!match) return {};
33
+ function parseFrontmatter(content) {
34
+ const match = content.match(/^---\s*\n([\s\S]*?)\n---/);
35
+ if (!match) return {};
28
36
  const fm = {};
29
37
  for (const line of match[1].split("\n")) {
30
38
  const sep = line.indexOf(":");
@@ -34,16 +42,16 @@ function parseFrontmatter(content) {
34
42
  fm[key] = val;
35
43
  }
36
44
  }
37
- return fm;
38
- }
39
-
40
- function getSkillsDir(root) {
41
- return config.ensureContext(root).paths.skillsDir;
42
- }
43
-
44
- function getRegistryPath(root) {
45
- return config.ensureContext(root).paths.registryPath;
46
- }
45
+ return fm;
46
+ }
47
+
48
+ function getSkillsDir(root) {
49
+ return config.ensureContext(root).paths.skillsDir;
50
+ }
51
+
52
+ function getRegistryPath(root) {
53
+ return config.ensureContext(root).paths.registryPath;
54
+ }
47
55
 
48
56
  function catalogSkills() {
49
57
  if (!fs.existsSync(SKILLS_TEMPLATES_DIR)) return [];
@@ -58,28 +66,37 @@ function catalogSkills() {
58
66
  .filter(Boolean);
59
67
  }
60
68
 
61
- function installedSkills(root) {
62
- const skillsDir = getSkillsDir(root);
63
- if (!fs.existsSync(skillsDir)) return [];
64
- return fs.readdirSync(skillsDir, { withFileTypes: true })
65
- .filter((e) => e.isDirectory() && fs.existsSync(path.join(skillsDir, e.name, "SKILL.md")))
66
- .map((e) => {
67
- const fm = parseFrontmatter(fs.readFileSync(path.join(skillsDir, e.name, "SKILL.md"), "utf8"));
68
- return { name: e.name, description: fm.description || "", version: fm.version || "1.0" };
69
- })
70
- .filter(Boolean);
71
- }
69
+ function installedSkills(root) {
70
+ const skillsDir = getSkillsDir(root);
71
+ if (!fs.existsSync(skillsDir)) return [];
72
+ const skills = fs.readdirSync(skillsDir, { withFileTypes: true })
73
+ .filter((e) => e.isDirectory() && fs.existsSync(path.join(skillsDir, e.name, "SKILL.md")))
74
+ .map((e) => {
75
+ const fm = parseFrontmatter(fs.readFileSync(path.join(skillsDir, e.name, "SKILL.md"), "utf8"));
76
+ return { name: e.name, description: fm.description || "", version: fm.version || "1.0" };
77
+ })
78
+ .filter(Boolean);
79
+ skills.sort((a, b) => {
80
+ const ai = INSTALLED_SKILL_PRIORITY.indexOf(a.name);
81
+ const bi = INSTALLED_SKILL_PRIORITY.indexOf(b.name);
82
+ const ap = ai >= 0 ? ai : INSTALLED_SKILL_PRIORITY.length;
83
+ const bp = bi >= 0 ? bi : INSTALLED_SKILL_PRIORITY.length;
84
+ if (ap !== bp) return ap - bp;
85
+ return a.name.localeCompare(b.name);
86
+ });
87
+ return skills;
88
+ }
72
89
 
73
90
  function updateRegistry(root) {
74
91
  const registryPath = getRegistryPath(root);
75
92
  fs.mkdirSync(path.dirname(registryPath), { recursive: true });
76
- let locale = "es";
77
- const context = config.ensureContext(root);
78
- const controlFile = config.controlFilePath(context);
79
- if (fs.existsSync(controlFile)) {
80
- try {
81
- locale = config.getLocale(config.loadControl(context));
82
- setLocale(locale);
93
+ let locale = "es";
94
+ const context = config.ensureContext(root);
95
+ const controlFile = config.controlFilePath(context);
96
+ if (fs.existsSync(controlFile)) {
97
+ try {
98
+ locale = config.getLocale(config.loadControl(context));
99
+ setLocale(locale);
83
100
  } catch (_error) {
84
101
  setLocale("es");
85
102
  }
@@ -97,29 +114,29 @@ function updateRegistry(root) {
97
114
  fs.writeFileSync(registryPath, lines.join("\n") + "\n", "utf8");
98
115
 
99
116
  // Also update control meta
100
- if (fs.existsSync(controlFile)) {
101
- try {
102
- const control = config.loadControl(context);
103
- if (control.meta.opera) {
104
- control.meta.opera.skills = skills.map((s) => s.name);
105
- config.saveControl(context, control);
106
- }
117
+ if (fs.existsSync(controlFile)) {
118
+ try {
119
+ const control = config.loadControl(context);
120
+ if (control.meta.opera) {
121
+ control.meta.opera.skills = skills.map((s) => s.name);
122
+ config.saveControl(context, control);
123
+ }
107
124
  } catch (_e) { /* ignore */ }
108
125
  }
109
126
  }
110
127
 
111
- function installSkill(root, skillName) {
112
- const context = config.ensureContext(root);
113
- const control = config.loadControl(context);
114
- setLocale(config.getLocale(control));
115
- const locale = config.getLocale(control);
128
+ function installSkill(root, skillName) {
129
+ const context = config.ensureContext(root);
130
+ const control = config.loadControl(context);
131
+ setLocale(config.getLocale(control));
132
+ const locale = config.getLocale(control);
116
133
 
117
134
  const templateDir = path.join(SKILLS_TEMPLATES_DIR, skillName);
118
135
  if (!fs.existsSync(templateDir)) {
119
136
  throw new Error(t("skill.notFound", { name: skillName }));
120
137
  }
121
138
 
122
- const targetDir = path.join(getSkillsDir(context), skillName);
139
+ const targetDir = path.join(getSkillsDir(context), skillName);
123
140
  if (fs.existsSync(path.join(targetDir, "SKILL.md"))) {
124
141
  console.log(t("skill.alreadyInstalled", { name: skillName }));
125
142
  return;
@@ -130,25 +147,25 @@ function installSkill(root, skillName) {
130
147
  if (localizedSkill) {
131
148
  fs.copyFileSync(localizedSkill, path.join(targetDir, "SKILL.md"));
132
149
  }
133
- updateRegistry(context);
134
- console.log(t("skill.installed", { name: skillName }));
135
- }
136
-
137
- function removeSkill(root, skillName) {
138
- const context = config.ensureContext(root);
139
- const control = config.loadControl(context);
140
- setLocale(config.getLocale(control));
141
-
142
- const targetDir = path.join(getSkillsDir(context), skillName);
150
+ updateRegistry(context);
151
+ console.log(t("skill.installed", { name: skillName }));
152
+ }
153
+
154
+ function removeSkill(root, skillName) {
155
+ const context = config.ensureContext(root);
156
+ const control = config.loadControl(context);
157
+ setLocale(config.getLocale(control));
158
+
159
+ const targetDir = path.join(getSkillsDir(context), skillName);
143
160
  if (!fs.existsSync(targetDir)) {
144
161
  console.log(t("skill.notInstalled", { name: skillName }));
145
162
  return;
146
163
  }
147
164
 
148
165
  fs.rmSync(targetDir, { recursive: true, force: true });
149
- updateRegistry(context);
150
- console.log(t("skill.removed", { name: skillName }));
151
- }
166
+ updateRegistry(context);
167
+ console.log(t("skill.removed", { name: skillName }));
168
+ }
152
169
 
153
170
  /* ── CLI commands ── */
154
171