trackops 1.1.0 → 2.0.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 +194 -230
- package/bin/trackops.js +54 -28
- package/lib/config.js +14 -10
- package/lib/control.js +44 -32
- package/lib/env.js +18 -1
- package/lib/init.js +40 -6
- package/lib/opera-bootstrap.js +825 -273
- package/lib/opera.js +360 -110
- package/lib/preferences.js +74 -0
- package/lib/runtime-state.js +144 -0
- package/lib/server.js +155 -25
- package/locales/en.json +136 -42
- package/locales/es.json +136 -42
- package/package.json +2 -1
- package/scripts/postinstall-locale.js +21 -0
- package/scripts/smoke-tests.js +130 -5
- package/scripts/validate-skill.js +2 -1
- package/skills/trackops/SKILL.md +57 -32
- package/skills/trackops/agents/openai.yaml +1 -1
- package/skills/trackops/references/activation.md +50 -16
- package/skills/trackops/references/troubleshooting.md +35 -20
- package/skills/trackops/references/workflow.md +18 -12
- package/skills/trackops/scripts/bootstrap-trackops.js +9 -7
- package/skills/trackops/skill.json +4 -4
- package/templates/opera/agent.md +10 -9
- package/templates/opera/architecture/dependency-graph.md +24 -0
- package/templates/opera/architecture/runtime-automation.md +24 -0
- package/templates/opera/architecture/runtime-operations.md +34 -0
- package/templates/opera/en/agent.md +21 -20
- package/templates/opera/en/architecture/dependency-graph.md +24 -0
- package/templates/opera/en/architecture/runtime-automation.md +24 -0
- package/templates/opera/en/architecture/runtime-operations.md +34 -0
- package/templates/opera/en/reviews/delivery-audit.md +18 -0
- package/templates/opera/en/reviews/integration-audit.md +18 -0
- package/templates/opera/en/router.md +19 -9
- package/templates/opera/reviews/delivery-audit.md +18 -0
- package/templates/opera/reviews/integration-audit.md +18 -0
- package/templates/opera/router.md +15 -5
- package/templates/skills/opera-contract-auditor/SKILL.md +38 -0
- package/templates/skills/opera-contract-auditor/locales/en/SKILL.md +38 -0
- package/templates/skills/opera-policy-guard/SKILL.md +26 -0
- package/templates/skills/opera-policy-guard/locales/en/SKILL.md +26 -0
- package/templates/skills/project-starter-skill/SKILL.md +89 -164
- package/templates/skills/project-starter-skill/locales/en/SKILL.md +104 -24
- package/ui/js/views/overview.js +16 -12
- package/templates/etapa/agent.md +0 -26
- package/templates/etapa/genesis.md +0 -94
- package/templates/etapa/references/autonomy-and-recovery.md +0 -117
- package/templates/etapa/references/etapa-cycle.md +0 -193
- package/templates/etapa/registry.md +0 -28
- package/templates/etapa/router.md +0 -39
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const os = require("os");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
|
|
7
|
+
const { detectSystemLocale, isInteractive, normalizeLocale, promptForLocale } = require("./locale");
|
|
8
|
+
|
|
9
|
+
function getRuntimeHome() {
|
|
10
|
+
return process.env.TRACKOPS_BOOTSTRAP_HOME || os.homedir();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function getRuntimeDir() {
|
|
14
|
+
return path.join(getRuntimeHome(), ".trackops");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function getRuntimeFile() {
|
|
18
|
+
return path.join(getRuntimeDir(), "runtime.json");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function defaultRuntimeState() {
|
|
22
|
+
return {
|
|
23
|
+
locale: null,
|
|
24
|
+
localeSource: null,
|
|
25
|
+
skill: null,
|
|
26
|
+
skillVersion: null,
|
|
27
|
+
runtimePackage: "trackops",
|
|
28
|
+
runtimeVersion: null,
|
|
29
|
+
bootstrapPolicy: null,
|
|
30
|
+
supportedAgentsV1: [],
|
|
31
|
+
verifiedAt: null,
|
|
32
|
+
verifiedWith: null,
|
|
33
|
+
executable: null,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function normalizeRuntimeState(state) {
|
|
38
|
+
const base = defaultRuntimeState();
|
|
39
|
+
const next = { ...base, ...(state || {}) };
|
|
40
|
+
next.locale = normalizeLocale(next.locale);
|
|
41
|
+
next.localeSource = next.localeSource || null;
|
|
42
|
+
next.supportedAgentsV1 = Array.isArray(next.supportedAgentsV1) ? next.supportedAgentsV1 : [];
|
|
43
|
+
return next;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function readRuntimeState() {
|
|
47
|
+
const file = getRuntimeFile();
|
|
48
|
+
if (!fs.existsSync(file)) return defaultRuntimeState();
|
|
49
|
+
try {
|
|
50
|
+
return normalizeRuntimeState(JSON.parse(fs.readFileSync(file, "utf8")));
|
|
51
|
+
} catch (_error) {
|
|
52
|
+
return defaultRuntimeState();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function writeRuntimeState(patch) {
|
|
57
|
+
const file = getRuntimeFile();
|
|
58
|
+
const state = normalizeRuntimeState({ ...readRuntimeState(), ...(patch || {}) });
|
|
59
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
60
|
+
fs.writeFileSync(file, `${JSON.stringify(state, null, 2)}\n`, "utf8");
|
|
61
|
+
return state;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function getGlobalLocale() {
|
|
65
|
+
return readRuntimeState().locale || null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function resolveLocaleState(options = {}) {
|
|
69
|
+
const runtime = readRuntimeState();
|
|
70
|
+
const explicit = normalizeLocale(options.explicitLocale);
|
|
71
|
+
if (explicit) return { locale: explicit, source: "explicit", runtime };
|
|
72
|
+
|
|
73
|
+
const project = normalizeLocale(options.projectLocale);
|
|
74
|
+
if (project) return { locale: project, source: "project", runtime };
|
|
75
|
+
|
|
76
|
+
const global = normalizeLocale(runtime.locale);
|
|
77
|
+
if (global) return { locale: global, source: "global", runtime };
|
|
78
|
+
|
|
79
|
+
const envLocale = normalizeLocale(process.env.TRACKOPS_LOCALE);
|
|
80
|
+
if (envLocale) return { locale: envLocale, source: "env", runtime };
|
|
81
|
+
|
|
82
|
+
const system = detectSystemLocale();
|
|
83
|
+
return { locale: system || "es", source: "system", runtime };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function ensureGlobalLocale(options = {}) {
|
|
87
|
+
const current = readRuntimeState();
|
|
88
|
+
const explicit = normalizeLocale(options.preferredLocale);
|
|
89
|
+
if (explicit) {
|
|
90
|
+
return {
|
|
91
|
+
locale: explicit,
|
|
92
|
+
source: "explicit",
|
|
93
|
+
runtime: writeRuntimeState({ locale: explicit, localeSource: "explicit" }),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (normalizeLocale(current.locale)) {
|
|
98
|
+
return { locale: current.locale, source: "global", runtime: current };
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
let locale = null;
|
|
102
|
+
let source = null;
|
|
103
|
+
if (options.interactive !== false && isInteractive()) {
|
|
104
|
+
locale = await promptForLocale(detectSystemLocale());
|
|
105
|
+
source = "prompt";
|
|
106
|
+
} else {
|
|
107
|
+
locale = detectSystemLocale() || "es";
|
|
108
|
+
source = "system";
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
locale,
|
|
113
|
+
source,
|
|
114
|
+
runtime: writeRuntimeState({ locale, localeSource: source }),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function doctorLocale(projectLocale = null, explicitLocale = null) {
|
|
119
|
+
const resolved = resolveLocaleState({ explicitLocale, projectLocale });
|
|
120
|
+
const runtime = readRuntimeState();
|
|
121
|
+
return {
|
|
122
|
+
effectiveLocale: resolved.locale || "es",
|
|
123
|
+
source: resolved.source,
|
|
124
|
+
projectLocale: normalizeLocale(projectLocale),
|
|
125
|
+
globalLocale: normalizeLocale(runtime.locale),
|
|
126
|
+
envLocale: normalizeLocale(process.env.TRACKOPS_LOCALE),
|
|
127
|
+
systemLocale: detectSystemLocale() || "es",
|
|
128
|
+
runtimeFile: getRuntimeFile(),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
module.exports = {
|
|
133
|
+
getRuntimeHome,
|
|
134
|
+
getRuntimeDir,
|
|
135
|
+
getRuntimeFile,
|
|
136
|
+
defaultRuntimeState,
|
|
137
|
+
normalizeRuntimeState,
|
|
138
|
+
readRuntimeState,
|
|
139
|
+
writeRuntimeState,
|
|
140
|
+
getGlobalLocale,
|
|
141
|
+
resolveLocaleState,
|
|
142
|
+
ensureGlobalLocale,
|
|
143
|
+
doctorLocale,
|
|
144
|
+
};
|
package/lib/server.js
CHANGED
|
@@ -11,8 +11,9 @@ const config = require("./config");
|
|
|
11
11
|
const control = require("./control");
|
|
12
12
|
const env = require("./env");
|
|
13
13
|
const registry = require("./registry");
|
|
14
|
-
const { t, setLocale, getMessages } = require("./i18n");
|
|
15
|
-
const { normalizeLocale } = require("./locale");
|
|
14
|
+
const { t, setLocale, getMessages } = require("./i18n");
|
|
15
|
+
const { normalizeLocale } = require("./locale");
|
|
16
|
+
const runtimeState = require("./runtime-state");
|
|
16
17
|
|
|
17
18
|
const UI_DIR = path.join(__dirname, "..", "ui");
|
|
18
19
|
const DEFAULT_HOST = "127.0.0.1";
|
|
@@ -41,10 +42,19 @@ function sendJson(res, statusCode, payload) {
|
|
|
41
42
|
res.end(JSON.stringify(payload));
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
function sendText(res, statusCode, message) {
|
|
45
|
-
res.writeHead(statusCode, { "Content-Type": "text/plain; charset=utf-8", "Cache-Control": "no-store" });
|
|
46
|
-
res.end(message);
|
|
47
|
-
}
|
|
45
|
+
function sendText(res, statusCode, message) {
|
|
46
|
+
res.writeHead(statusCode, { "Content-Type": "text/plain; charset=utf-8", "Cache-Control": "no-store" });
|
|
47
|
+
res.end(message);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function readJsonFileSafe(filePath) {
|
|
51
|
+
if (!filePath || !fs.existsSync(filePath)) return null;
|
|
52
|
+
try {
|
|
53
|
+
return JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
54
|
+
} catch (_error) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
48
58
|
|
|
49
59
|
function parseBody(req) {
|
|
50
60
|
return new Promise((resolve, reject) => {
|
|
@@ -355,22 +365,50 @@ function loadControlApi(projectRoot) {
|
|
|
355
365
|
return control.forProject(projectRoot);
|
|
356
366
|
}
|
|
357
367
|
|
|
358
|
-
function buildI18nPayload(controlState) {
|
|
368
|
+
function buildI18nPayload(controlState) {
|
|
359
369
|
const phases = config.getPhases(controlState);
|
|
360
370
|
const locale = config.getLocale(controlState);
|
|
361
371
|
const statusLabels = {};
|
|
362
372
|
for (const s of control.STATUS_ORDER) {
|
|
363
373
|
statusLabels[s] = control.statusLabel(s);
|
|
364
374
|
}
|
|
365
|
-
return { locale, statusLabels, phases, messages: getMessages(locale) };
|
|
366
|
-
}
|
|
367
|
-
|
|
375
|
+
return { locale, statusLabels, phases, messages: getMessages(locale) };
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
function buildOperaState(projectRoot, controlState) {
|
|
379
|
+
const context = config.ensureContext(projectRoot);
|
|
380
|
+
const operaBootstrap = require("./opera-bootstrap");
|
|
381
|
+
const bootstrapState =
|
|
382
|
+
controlState.meta?.opera?.bootstrap ||
|
|
383
|
+
operaBootstrap.detectLegacyBootstrap(context, controlState) ||
|
|
384
|
+
operaBootstrap.createAwaitingBootstrapState(context);
|
|
385
|
+
const qualityReport = readJsonFileSafe(path.join(context.paths.bootstrapDir, "quality-report.json"));
|
|
386
|
+
const localeDoctor = runtimeState.doctorLocale(controlState.meta?.locale || null);
|
|
387
|
+
|
|
388
|
+
return {
|
|
389
|
+
installed: config.isOperaInstalled(controlState),
|
|
390
|
+
version: controlState.meta?.opera?.version || null,
|
|
391
|
+
model: controlState.meta?.opera?.model || null,
|
|
392
|
+
stableTag: controlState.meta?.opera?.stableTag || null,
|
|
393
|
+
contractVersion: controlState.meta?.opera?.contractVersion || null,
|
|
394
|
+
contractReadiness: controlState.meta?.opera?.contractReadiness || qualityReport?.contractReadiness || "hypothesis",
|
|
395
|
+
qualityStatus: controlState.meta?.opera?.qualityStatus || qualityReport?.status || null,
|
|
396
|
+
qualityReport,
|
|
397
|
+
legacyStatus: controlState.meta?.opera?.legacyStatus || bootstrapState?.status || "supported",
|
|
398
|
+
localeSource: localeDoctor.source,
|
|
399
|
+
bootstrap: bootstrapState,
|
|
400
|
+
contractFile: context.paths.contractFile,
|
|
401
|
+
policyFile: context.paths.autonomyPolicyFile,
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
|
|
368
405
|
function getStatePayload(projectRef) {
|
|
369
406
|
const project = resolveProjectEntry(projectRef);
|
|
370
407
|
const api = loadControlApi(project.root);
|
|
371
408
|
const controlState = api.loadControl();
|
|
372
409
|
const runtime = api.refreshRepoRuntime({ quiet: true });
|
|
373
410
|
const envState = env.auditEnvironment(project.root, controlState);
|
|
411
|
+
const operaState = buildOperaState(project.root, controlState);
|
|
374
412
|
|
|
375
413
|
return {
|
|
376
414
|
project,
|
|
@@ -378,6 +416,7 @@ function getStatePayload(projectRef) {
|
|
|
378
416
|
derived: api.derive(controlState),
|
|
379
417
|
runtime,
|
|
380
418
|
env: envState,
|
|
419
|
+
opera: operaState,
|
|
381
420
|
docsDirty: api.getDocDrift(controlState),
|
|
382
421
|
i18n: buildI18nPayload(controlState),
|
|
383
422
|
generatedAt: new Date().toISOString(),
|
|
@@ -611,18 +650,23 @@ async function handleApi(req, res, url) {
|
|
|
611
650
|
if (!body.root) { sendJson(res, 400, { ok: false, error: "Project path required." }); return; }
|
|
612
651
|
try {
|
|
613
652
|
const initMod = require("./init");
|
|
614
|
-
const result = initMod.initProject(body.root, { locale: body.locale || null });
|
|
615
|
-
if (body.withOpera) {
|
|
616
|
-
const opera = require("./opera");
|
|
617
|
-
await opera.install(result.root, {
|
|
618
|
-
locale: body.locale || null,
|
|
619
|
-
bootstrap: body.bootstrap !== false,
|
|
620
|
-
interactive: false,
|
|
621
|
-
answers: body.bootstrapAnswers || {},
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
653
|
+
const result = initMod.initProject(body.root, { locale: body.locale || null });
|
|
654
|
+
if (body.withOpera) {
|
|
655
|
+
const opera = require("./opera");
|
|
656
|
+
await opera.install(result.root, {
|
|
657
|
+
locale: body.locale || null,
|
|
658
|
+
bootstrap: body.bootstrap !== false,
|
|
659
|
+
interactive: false,
|
|
660
|
+
answers: body.bootstrapAnswers || {},
|
|
661
|
+
bootstrapMode: body.bootstrapMode || "auto",
|
|
662
|
+
technicalLevel: body.technicalLevel || null,
|
|
663
|
+
projectState: body.projectState || null,
|
|
664
|
+
docsState: body.docsState || null,
|
|
665
|
+
decisionOwnership: body.decisionOwnership || null,
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
const project = registry.registerProject(result.root);
|
|
669
|
+
sendJson(res, 201, { ok: true, project, projects: registry.listProjects() });
|
|
626
670
|
} catch (err) {
|
|
627
671
|
sendJson(res, 500, { ok: false, error: err.message });
|
|
628
672
|
}
|
|
@@ -706,8 +750,94 @@ async function handleApi(req, res, url) {
|
|
|
706
750
|
sendJson(res, 200, result);
|
|
707
751
|
return;
|
|
708
752
|
}
|
|
709
|
-
|
|
710
|
-
if (req.method === "
|
|
753
|
+
|
|
754
|
+
if (req.method === "GET" && url.pathname === "/api/opera/bootstrap") {
|
|
755
|
+
const project = resolveProjectEntry(url.searchParams.get("project"));
|
|
756
|
+
const api = loadControlApi(project.root);
|
|
757
|
+
const controlState = api.loadControl();
|
|
758
|
+
const operaState = buildOperaState(project.root, controlState);
|
|
759
|
+
const bootstrap = operaState.bootstrap;
|
|
760
|
+
sendJson(res, 200, {
|
|
761
|
+
ok: true,
|
|
762
|
+
mode: bootstrap.mode || null,
|
|
763
|
+
status: bootstrap.status || "awaiting_intake",
|
|
764
|
+
technicalLevel: bootstrap.technicalLevel || null,
|
|
765
|
+
projectState: bootstrap.projectState || null,
|
|
766
|
+
documentationState: bootstrap.documentationState || null,
|
|
767
|
+
decisionOwnership: bootstrap.decisionOwnership || null,
|
|
768
|
+
handoffFiles: bootstrap.handoffFiles || null,
|
|
769
|
+
intakeFiles: bootstrap.intakeFiles || null,
|
|
770
|
+
reviewFiles: bootstrap.reviewFiles || null,
|
|
771
|
+
contractVersion: operaState.contractVersion,
|
|
772
|
+
contractReadiness: operaState.contractReadiness,
|
|
773
|
+
legacyStatus: operaState.legacyStatus,
|
|
774
|
+
qualityReport: operaState.qualityReport,
|
|
775
|
+
});
|
|
776
|
+
return;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
if (req.method === "GET" && url.pathname === "/api/opera/handoff") {
|
|
780
|
+
const project = resolveProjectEntry(url.searchParams.get("project"));
|
|
781
|
+
const context = config.ensureContext(project.root);
|
|
782
|
+
const operaBootstrap = require("./opera-bootstrap");
|
|
783
|
+
const files = operaBootstrap.bootstrapFilePaths(context);
|
|
784
|
+
let handoffJson = null;
|
|
785
|
+
if (fs.existsSync(files.json)) {
|
|
786
|
+
try {
|
|
787
|
+
handoffJson = JSON.parse(fs.readFileSync(files.json, "utf8"));
|
|
788
|
+
} catch (_error) {
|
|
789
|
+
handoffJson = null;
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
sendJson(res, 200, {
|
|
793
|
+
ok: true,
|
|
794
|
+
markdownFile: files.markdown,
|
|
795
|
+
jsonFile: files.json,
|
|
796
|
+
openQuestionsFile: files.openQuestions,
|
|
797
|
+
qualityReportFile: files.qualityReport,
|
|
798
|
+
markdown: fs.existsSync(files.markdown) ? fs.readFileSync(files.markdown, "utf8") : "",
|
|
799
|
+
json: handoffJson,
|
|
800
|
+
openQuestions: fs.existsSync(files.openQuestions) ? fs.readFileSync(files.openQuestions, "utf8") : "",
|
|
801
|
+
qualityReport: readJsonFileSafe(files.qualityReport),
|
|
802
|
+
});
|
|
803
|
+
return;
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
if (req.method === "POST" && url.pathname === "/api/opera/bootstrap/intake") {
|
|
807
|
+
const body = await parseBody(req);
|
|
808
|
+
const project = resolveProjectEntry(body.projectId || body.project || url.searchParams.get("project"));
|
|
809
|
+
const opera = require("./opera");
|
|
810
|
+
const profile = await opera.runBootstrap(project.root, {
|
|
811
|
+
interactive: false,
|
|
812
|
+
bootstrapMode: body.bootstrapMode || "auto",
|
|
813
|
+
technicalLevel: body.technicalLevel || null,
|
|
814
|
+
projectState: body.projectState || null,
|
|
815
|
+
docsState: body.documentationState || body.docsState || null,
|
|
816
|
+
decisionOwnership: body.decisionOwnership || null,
|
|
817
|
+
answers: body.answers || {},
|
|
818
|
+
});
|
|
819
|
+
sendJson(res, 200, { ok: true, profile, state: getStatePayload(project.id) });
|
|
820
|
+
return;
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
if (req.method === "GET" && url.pathname === "/api/opera/status") {
|
|
824
|
+
const project = resolveProjectEntry(url.searchParams.get("project"));
|
|
825
|
+
const api = loadControlApi(project.root);
|
|
826
|
+
const controlState = api.loadControl();
|
|
827
|
+
sendJson(res, 200, { ok: true, ...buildOperaState(project.root, controlState) });
|
|
828
|
+
return;
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
if (req.method === "POST" && url.pathname === "/api/opera/bootstrap/resume") {
|
|
832
|
+
const body = await parseBody(req);
|
|
833
|
+
const project = resolveProjectEntry(body.projectId || body.project || url.searchParams.get("project"));
|
|
834
|
+
const opera = require("./opera");
|
|
835
|
+
const profile = await opera.runBootstrap(project.root, { interactive: false, resume: true });
|
|
836
|
+
sendJson(res, 200, { ok: true, profile, state: getStatePayload(project.id) });
|
|
837
|
+
return;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
if (req.method === "POST" && url.pathname === "/api/commands") {
|
|
711
841
|
const body = await parseBody(req);
|
|
712
842
|
const project = resolveProjectEntry(body.projectId || body.project || url.searchParams.get("project"));
|
|
713
843
|
const commandText = String(body.command || "").trim();
|
|
@@ -831,7 +961,7 @@ async function handleApi(req, res, url) {
|
|
|
831
961
|
const catalog = [
|
|
832
962
|
{ id: "changelog-updater", title: "Changelog Updater", description: "Mantiene automatizado el CHANGELOG basado en commits.", url: "https://skills.sh/changelog-updater.md" },
|
|
833
963
|
{ id: "commiter", title: "Git Commiter", description: "Genera mensajes de commit strictos siguiendo Conventional Commits y Emojis.", url: "https://skills.sh/commiter.md" },
|
|
834
|
-
{ id: "project-starter-skill", title: "Project Starter", description: "Skill para
|
|
964
|
+
{ id: "project-starter-skill", title: "Project Starter", description: "Skill para discovery y estructuracion inicial guiada con TrackOps y OPERA.", url: "https://skills.sh/project-starter.md" },
|
|
835
965
|
{ id: "tdd-master", title: "TDD Master", description: "Fuerza el ciclo Red-Green-Refactor en las implementaciones.", url: "https://skills.sh/tdd-master.md" },
|
|
836
966
|
{ id: "e2e-tester", title: "E2E Tester", description: "Plantillas y comandos para frameworks de Test End-to-End.", url: "https://skills.sh/e2e-tester.md" }
|
|
837
967
|
];
|
package/locales/en.json
CHANGED
|
@@ -101,8 +101,58 @@
|
|
|
101
101
|
"cli.next.stream": "stream",
|
|
102
102
|
"cli.next.summary": "summary",
|
|
103
103
|
|
|
104
|
-
"cli.help.title": "Project operational control",
|
|
105
|
-
"cli.help.usage": "Usage:",
|
|
104
|
+
"cli.help.title": "Project operational control",
|
|
105
|
+
"cli.help.usage": "Usage:",
|
|
106
|
+
"cli.help.commands": "Commands:",
|
|
107
|
+
"cli.help.init.desc": "Initialize TrackOps in the current directory.",
|
|
108
|
+
"cli.help.workspace.desc": "Show or migrate the current workspace layout.",
|
|
109
|
+
"cli.help.env.desc": "Audit or sync the workspace .env contract.",
|
|
110
|
+
"cli.help.release.desc": "Publish the configured app/ branch snapshot.",
|
|
111
|
+
"cli.help.version.desc": "Print the installed TrackOps version.",
|
|
112
|
+
"cli.help.status.desc": "Show project state: focus, active phase, ready tasks, blockers, repo.",
|
|
113
|
+
"cli.help.next.desc": "Prioritized queue of next executable tasks.",
|
|
114
|
+
"cli.help.sync.desc": "Regenerate task_plan.md, progress.md and findings.md from project_control.json.",
|
|
115
|
+
"cli.help.dashboard.desc": "Launch the local web dashboard on a free port and print local/network URLs.",
|
|
116
|
+
"cli.help.refreshRepo.desc": "Update the repo runtime snapshot with git state.",
|
|
117
|
+
"cli.help.installHooks.desc": "Configure git core.hooksPath to use the TrackOps hooks directory.",
|
|
118
|
+
"cli.help.register.desc": "Register the current project in the multi-project portfolio.",
|
|
119
|
+
"cli.help.projects.desc": "List registered projects.",
|
|
120
|
+
"cli.help.task.desc": "Actions: start, review, complete, block, pending, cancel, note.",
|
|
121
|
+
"cli.help.opera.desc": "Manage OPERA.",
|
|
122
|
+
"cli.help.opera.upgradeHint": "Upgrade: trackops opera upgrade --stable [--reset]",
|
|
123
|
+
"cli.help.locale.desc": "Show or update the global TrackOps language.",
|
|
124
|
+
"cli.help.doctor.desc": "Explain the effective language source for this machine/project.",
|
|
125
|
+
"cli.help.skill.desc": "Manage skills.",
|
|
126
|
+
"cli.help.help.desc": "Show this help.",
|
|
127
|
+
"cli.help.globalWorkflow": "Global agent workflow:",
|
|
128
|
+
"cli.help.globalWorkflow.line1": "Install with 'npx skills add Baxahaun/trackops'",
|
|
129
|
+
"cli.help.globalWorkflow.line2": "and the global/agent flags you need; then use 'trackops init' and 'trackops opera install' explicitly inside each project.",
|
|
130
|
+
"cli.usage.workspace": "Usage: trackops workspace <status|migrate>",
|
|
131
|
+
"cli.usage.env": "Usage: trackops env <status|sync>",
|
|
132
|
+
"cli.usage.opera": "Usage: trackops opera <install|bootstrap|handoff|status|configure|upgrade>",
|
|
133
|
+
"cli.usage.skill": "Usage: trackops skill <install|list|remove|catalog> [name]",
|
|
134
|
+
"cli.usage.locale": "Usage: trackops locale <get|set> [es|en]",
|
|
135
|
+
"cli.usage.doctor": "Usage: trackops doctor locale",
|
|
136
|
+
"cli.error.unknownCommand": "Unknown command: {command}",
|
|
137
|
+
"cli.error.runHelp": "Run 'trackops help' for usage.",
|
|
138
|
+
"cli.error.noWorkspace": "No TrackOps workspace found in this directory or any parent.",
|
|
139
|
+
"locale.effective": "Effective language",
|
|
140
|
+
"locale.source": "Source",
|
|
141
|
+
"locale.global": "Global language",
|
|
142
|
+
"locale.project": "Project language",
|
|
143
|
+
"locale.env": "Environment language",
|
|
144
|
+
"locale.system": "System language",
|
|
145
|
+
"locale.runtimeFile": "Runtime file",
|
|
146
|
+
"locale.none": "none",
|
|
147
|
+
"locale.invalid": "Invalid locale: {value}.",
|
|
148
|
+
"locale.updated": "Global language updated to {locale}.",
|
|
149
|
+
"locale.source.explicit": "explicit flag",
|
|
150
|
+
"locale.source.project": "project",
|
|
151
|
+
"locale.source.global": "global",
|
|
152
|
+
"locale.source.env": "environment",
|
|
153
|
+
"locale.source.system": "system",
|
|
154
|
+
"locale.source.prompt": "prompt",
|
|
155
|
+
"locale.source.manual": "manual",
|
|
106
156
|
|
|
107
157
|
"server.ready": "Ops dashboard ready at http://{host}:{port}",
|
|
108
158
|
"server.bannerTitle": "Serving!",
|
|
@@ -138,11 +188,34 @@
|
|
|
138
188
|
"init.defaultTaskTitle": "Set up project with trackops",
|
|
139
189
|
"init.defaultTaskSummary": "Verify initial structure, adjust phases and confirm operational integration.",
|
|
140
190
|
|
|
141
|
-
"opera.installed": "OPERA methodology installed (v{version}).",
|
|
142
|
-
"opera.alreadyInstalled": "OPERA is already installed in this project (v{version}).",
|
|
143
|
-
"opera.notInstalled": "OPERA is not installed in this project.",
|
|
144
|
-
"opera.upgraded": "OPERA upgraded to v{version}.",
|
|
145
|
-
"opera.primitiveDetected": "Existing OPERA installation detected (not managed by Ops).",
|
|
191
|
+
"opera.installed": "OPERA methodology installed (v{version}).",
|
|
192
|
+
"opera.alreadyInstalled": "OPERA is already installed in this project (v{version}).",
|
|
193
|
+
"opera.notInstalled": "OPERA is not installed in this project.",
|
|
194
|
+
"opera.upgraded": "OPERA upgraded to v{version}.",
|
|
195
|
+
"opera.primitiveDetected": "Existing OPERA installation detected (not managed by Ops).",
|
|
196
|
+
"opera.status.version": "OPERA v{version}",
|
|
197
|
+
"opera.status.installed": " Installed: {value}",
|
|
198
|
+
"opera.status.skills": " Skills: {value}",
|
|
199
|
+
"opera.status.locale": " Locale: {locale} ({source})",
|
|
200
|
+
"opera.status.legacy": " Legacy: {value}",
|
|
201
|
+
"opera.status.contractVersion": " Contract version: {value}",
|
|
202
|
+
"opera.status.contractReadiness": " Contract readiness: {value}",
|
|
203
|
+
"opera.status.bootstrap": " Bootstrap: {value}",
|
|
204
|
+
"opera.status.mode": " Mode: {value}",
|
|
205
|
+
"opera.status.route": " Route: {value}",
|
|
206
|
+
"opera.status.ownership": " Ownership: {value}",
|
|
207
|
+
"opera.status.missing": " Missing: {value}",
|
|
208
|
+
"opera.status.resume": " Resume: trackops opera bootstrap --resume",
|
|
209
|
+
"opera.status.handoff": " Handoff: {value}",
|
|
210
|
+
"opera.status.qualityReport": " Quality report: {value}",
|
|
211
|
+
"opera.status.structure": " Structure:",
|
|
212
|
+
"opera.configure.invalidPhases": "Invalid phases JSON.",
|
|
213
|
+
"opera.configure.updated": "Configuration updated.",
|
|
214
|
+
"opera.upgrade.runInstallFirst": "Run 'trackops opera install' first.",
|
|
215
|
+
"opera.upgrade.usage": "Usage: trackops opera upgrade --stable [--reset]",
|
|
216
|
+
"opera.upgrade.legacyUnsupported": "Legacy OPERA project detected. Run 'trackops opera upgrade --stable --reset' to move it to the current stable model.",
|
|
217
|
+
"opera.upgrade.backup": "Backup: {path}",
|
|
218
|
+
"postinstall.localeSet": "TrackOps set the language to '{locale}' ({source}).",
|
|
146
219
|
|
|
147
220
|
"skill.installed": "Skill '{name}' installed.",
|
|
148
221
|
"skill.removed": "Skill '{name}' uninstalled.",
|
|
@@ -154,35 +227,47 @@
|
|
|
154
227
|
|
|
155
228
|
"cli.status.bootstrap": "Bootstrap: {status} | Locale: {locale}",
|
|
156
229
|
|
|
157
|
-
"bootstrap.header": "OPERA bootstrap",
|
|
158
|
-
"bootstrap.subtitle": "
|
|
159
|
-
"bootstrap.question.
|
|
160
|
-
"bootstrap.question.
|
|
161
|
-
"bootstrap.question.
|
|
162
|
-
"bootstrap.question.
|
|
163
|
-
"bootstrap.question.
|
|
230
|
+
"bootstrap.header": "OPERA bootstrap",
|
|
231
|
+
"bootstrap.subtitle": "Classify the user and the project first. TrackOps will decide whether to continue in the terminal or route discovery to the agent.",
|
|
232
|
+
"bootstrap.question.technicalLevel": "User technical level",
|
|
233
|
+
"bootstrap.question.projectState": "Current project state",
|
|
234
|
+
"bootstrap.question.docsState": "Available documentation",
|
|
235
|
+
"bootstrap.question.decisionOwnership": "Who should own key decisions",
|
|
236
|
+
"bootstrap.question.problemStatement": "Main problem to solve",
|
|
237
|
+
"bootstrap.question.targetUser": "Primary target user",
|
|
238
|
+
"bootstrap.question.desiredOutcome": "Desired outcome",
|
|
239
|
+
"bootstrap.question.externalServices": "External services (comma separated)",
|
|
240
|
+
"bootstrap.question.sourceOfTruth": "Source of truth",
|
|
241
|
+
"bootstrap.question.payload": "Delivery payload / target",
|
|
242
|
+
"bootstrap.question.behaviorRules": "Behavior rules (semicolon separated)",
|
|
164
243
|
"bootstrap.question.inputSchema": "Input schema JSON",
|
|
165
244
|
"bootstrap.question.outputSchema": "Output schema JSON",
|
|
166
245
|
"bootstrap.question.invariants": "Architectural invariants (semicolon separated)",
|
|
167
246
|
"bootstrap.question.pipeline": "Pipeline steps (semicolon separated)",
|
|
168
|
-
"bootstrap.question.templates": "Template files (comma separated)",
|
|
169
|
-
"bootstrap.question.repoTasks": "Include optional repo tasks? [y/n]",
|
|
170
|
-
"bootstrap.completed": "OPERA bootstrap completed.",
|
|
171
|
-
"bootstrap.pending": "OPERA bootstrap saved as pending. Resume with 'trackops opera bootstrap --resume'.",
|
|
172
|
-
"bootstrap.
|
|
173
|
-
"bootstrap.
|
|
174
|
-
"bootstrap.
|
|
175
|
-
"bootstrap.
|
|
176
|
-
"bootstrap.
|
|
177
|
-
"bootstrap.
|
|
178
|
-
"bootstrap.
|
|
179
|
-
"bootstrap.
|
|
180
|
-
"bootstrap.
|
|
181
|
-
"bootstrap.
|
|
182
|
-
"bootstrap.
|
|
183
|
-
"bootstrap.acceptance.
|
|
184
|
-
"bootstrap.acceptance.
|
|
185
|
-
"bootstrap.acceptance.
|
|
247
|
+
"bootstrap.question.templates": "Template files (comma separated)",
|
|
248
|
+
"bootstrap.question.repoTasks": "Include optional repo tasks? [y/n]",
|
|
249
|
+
"bootstrap.completed": "OPERA bootstrap completed.",
|
|
250
|
+
"bootstrap.pending": "OPERA bootstrap saved as pending. Resume with 'trackops opera bootstrap --resume'.",
|
|
251
|
+
"bootstrap.awaitingAgent": "OPERA bootstrap has been routed to the agent. Complete the handoff and resume with 'trackops opera bootstrap --resume'.",
|
|
252
|
+
"bootstrap.handoffFile": "Handoff file",
|
|
253
|
+
"bootstrap.infer.envSourceHint": "Environment files detected",
|
|
254
|
+
"bootstrap.noneDefined": "Not defined yet.",
|
|
255
|
+
"bootstrap.pendingValue": "Pending definition.",
|
|
256
|
+
"bootstrap.servicePending": "pending",
|
|
257
|
+
"bootstrap.defaultFocus": "Complete OPERA bootstrap",
|
|
258
|
+
"bootstrap.defaultTarget": "Target delivery pending definition",
|
|
259
|
+
"bootstrap.blocker.missingData": "Core bootstrap data is still missing.",
|
|
260
|
+
"bootstrap.blocker.awaitingAgent": "Waiting for the agent handoff output.",
|
|
261
|
+
"bootstrap.history.seeded": "Seeded by OPERA bootstrap.",
|
|
262
|
+
"bootstrap.acceptance.discovery": "Discovery questions answered.",
|
|
263
|
+
"bootstrap.acceptance.schema": "Input/output schema defined in genesis.md.",
|
|
264
|
+
"bootstrap.acceptance.rules": "Behavior rules documented.",
|
|
265
|
+
"bootstrap.acceptance.plan": "Plan reviewed and accepted.",
|
|
266
|
+
"bootstrap.acceptance.intake": "The agent generated ops/bootstrap/intake.json.",
|
|
267
|
+
"bootstrap.acceptance.specDossier": "The agent generated ops/bootstrap/spec-dossier.md.",
|
|
268
|
+
"bootstrap.acceptance.resume": "OPERA ingested the context and continued.",
|
|
269
|
+
"bootstrap.acceptance.env": "Required credentials verified.",
|
|
270
|
+
"bootstrap.acceptance.tests": "Connectivity checks passing.",
|
|
186
271
|
"bootstrap.acceptance.shape": "External shapes validated against genesis.md.",
|
|
187
272
|
"bootstrap.acceptance.findings": "Findings documented.",
|
|
188
273
|
"bootstrap.acceptance.sops": "SOPs documented.",
|
|
@@ -196,9 +281,10 @@
|
|
|
196
281
|
"bootstrap.acceptance.deploy": "Deployment completed.",
|
|
197
282
|
"bootstrap.acceptance.triggers": "Triggers configured.",
|
|
198
283
|
"bootstrap.acceptance.smoke": "Smoke test passing.",
|
|
199
|
-
"bootstrap.task.bootstrap.title": "Complete OPERA bootstrap",
|
|
200
|
-
"bootstrap.task.bootstrap.summary": "Turn the installed OPERA structure into a project-specific operating model.",
|
|
201
|
-
"bootstrap.task.
|
|
284
|
+
"bootstrap.task.bootstrap.title": "Complete OPERA bootstrap",
|
|
285
|
+
"bootstrap.task.bootstrap.summary": "Turn the installed OPERA structure into a project-specific operating model.",
|
|
286
|
+
"bootstrap.task.bootstrap.handoffSummary": "Prepare the agent handoff so an idea or partial specification becomes structured operational context.",
|
|
287
|
+
"bootstrap.task.prove.title": "Validate integrations",
|
|
202
288
|
"bootstrap.task.prove.summary": "Verify credentials, connectivity, and response shapes before building further.",
|
|
203
289
|
"bootstrap.task.structure.title": "Structure the system",
|
|
204
290
|
"bootstrap.task.structure.summary": "Document SOPs, implement tools, and capture the dependency graph.",
|
|
@@ -214,13 +300,21 @@
|
|
|
214
300
|
"bootstrap.task.repoChangelog.summary": "Decide how CHANGELOG.md should be maintained in this project.",
|
|
215
301
|
"bootstrap.task.repoGithub.title": "Review GitHub governance tasks",
|
|
216
302
|
"bootstrap.task.repoGithub.summary": "Check whether repository automation or governance tasks should be enabled.",
|
|
217
|
-
"bootstrap.field.
|
|
218
|
-
"bootstrap.field.
|
|
219
|
-
"bootstrap.field.
|
|
220
|
-
"bootstrap.field.
|
|
221
|
-
"bootstrap.field.
|
|
222
|
-
"bootstrap.
|
|
223
|
-
"bootstrap.
|
|
303
|
+
"bootstrap.field.singularDesiredOutcome": "Desired outcome",
|
|
304
|
+
"bootstrap.field.desiredOutcome": "Desired outcome",
|
|
305
|
+
"bootstrap.field.problemStatement": "Problem statement",
|
|
306
|
+
"bootstrap.field.targetUser": "Target user",
|
|
307
|
+
"bootstrap.field.decisionOwnership": "Decision ownership",
|
|
308
|
+
"bootstrap.field.sourceOfTruth": "Source of truth",
|
|
309
|
+
"bootstrap.field.payload": "Payload",
|
|
310
|
+
"bootstrap.field.inputSchema": "Input schema",
|
|
311
|
+
"bootstrap.field.outputSchema": "Output schema",
|
|
312
|
+
"bootstrap.field.intakeJson": "intake.json file",
|
|
313
|
+
"bootstrap.field.specDossier": "spec-dossier.md file",
|
|
314
|
+
"bootstrap.decisionImpact": "Required to complete the OPERA bootstrap.",
|
|
315
|
+
"bootstrap.pendingDecision.handoff": "Send the TrackOps handoff to the agent",
|
|
316
|
+
"bootstrap.pendingDecision.handoffImpact": "Required so the agent can generate intake.json and spec-dossier.md.",
|
|
317
|
+
"bootstrap.finding.genesisConflictTitle": "Genesis requires manual review",
|
|
224
318
|
"bootstrap.finding.genesisConflictDetail": "TrackOps detected a non-template genesis.md and stopped automatic overwrite.",
|
|
225
319
|
"bootstrap.finding.genesisConflictImpact": "Bootstrap cannot be completed until the existing constitution is reviewed.",
|
|
226
320
|
|