trackops 1.1.0 → 2.0.1
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 +67 -45
- package/skills/trackops/agents/openai.yaml +5 -1
- package/skills/trackops/locales/en/SKILL.md +86 -0
- package/skills/trackops/locales/en/references/activation.md +73 -0
- package/skills/trackops/locales/en/references/troubleshooting.md +49 -0
- package/skills/trackops/locales/en/references/workflow.md +26 -0
- package/skills/trackops/references/activation.md +53 -19
- package/skills/trackops/references/troubleshooting.md +36 -21
- package/skills/trackops/references/workflow.md +21 -15
- 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
package/bin/trackops.js
CHANGED
|
@@ -2,22 +2,39 @@
|
|
|
2
2
|
|
|
3
3
|
const path = require("path");
|
|
4
4
|
const config = require("../lib/config");
|
|
5
|
+
const runtimeState = require("../lib/runtime-state");
|
|
6
|
+
const { setLocale, t } = require("../lib/i18n");
|
|
5
7
|
const pkg = require("../package.json");
|
|
6
|
-
|
|
7
|
-
const command = process.argv[2];
|
|
8
|
-
const args = process.argv.slice(3);
|
|
9
|
-
|
|
8
|
+
|
|
9
|
+
const command = process.argv[2];
|
|
10
|
+
const args = process.argv.slice(3);
|
|
11
|
+
|
|
12
|
+
function initCliLocale() {
|
|
13
|
+
let projectLocale = null;
|
|
14
|
+
try {
|
|
15
|
+
const context = config.resolveWorkspaceContext();
|
|
16
|
+
if (context) {
|
|
17
|
+
projectLocale = config.getLocale(config.loadControl(context));
|
|
18
|
+
}
|
|
19
|
+
} catch (_error) {
|
|
20
|
+
projectLocale = null;
|
|
21
|
+
}
|
|
22
|
+
const doctor = runtimeState.doctorLocale(projectLocale);
|
|
23
|
+
setLocale(doctor.effectiveLocale);
|
|
24
|
+
}
|
|
25
|
+
|
|
10
26
|
function resolveRoot() {
|
|
11
27
|
const context = config.resolveWorkspaceContext();
|
|
12
28
|
if (!context) {
|
|
13
|
-
console.error("
|
|
29
|
+
console.error(t("cli.error.noWorkspace"));
|
|
14
30
|
process.exit(1);
|
|
15
31
|
}
|
|
16
32
|
return context.workspaceRoot;
|
|
17
33
|
}
|
|
18
|
-
|
|
19
|
-
async function run() {
|
|
20
|
-
|
|
34
|
+
|
|
35
|
+
async function run() {
|
|
36
|
+
initCliLocale();
|
|
37
|
+
try {
|
|
21
38
|
switch (command) {
|
|
22
39
|
case "init":
|
|
23
40
|
await require("../lib/init").cmdInit(args);
|
|
@@ -65,7 +82,7 @@ async function run() {
|
|
|
65
82
|
const root = config.resolveProjectRoot() || process.cwd();
|
|
66
83
|
if (sub === "status") workspace.cmdStatus(root);
|
|
67
84
|
else if (sub === "migrate") workspace.cmdMigrate(root, args.slice(1));
|
|
68
|
-
else console.log("
|
|
85
|
+
else console.log(t("cli.usage.workspace"));
|
|
69
86
|
break;
|
|
70
87
|
}
|
|
71
88
|
|
|
@@ -75,7 +92,7 @@ async function run() {
|
|
|
75
92
|
const root = config.resolveProjectRoot() || process.cwd();
|
|
76
93
|
if (sub === "status") env.cmdStatus(root);
|
|
77
94
|
else if (sub === "sync") env.cmdSync(root);
|
|
78
|
-
else console.log("
|
|
95
|
+
else console.log(t("cli.usage.env"));
|
|
79
96
|
break;
|
|
80
97
|
}
|
|
81
98
|
|
|
@@ -83,18 +100,27 @@ async function run() {
|
|
|
83
100
|
require("../lib/release").cmdRelease(config.resolveProjectRoot() || process.cwd(), args);
|
|
84
101
|
break;
|
|
85
102
|
|
|
103
|
+
case "locale":
|
|
104
|
+
require("../lib/preferences").cmdLocale(args, config.resolveProjectRoot() || process.cwd());
|
|
105
|
+
break;
|
|
106
|
+
|
|
107
|
+
case "doctor":
|
|
108
|
+
require("../lib/preferences").cmdDoctor(args, config.resolveProjectRoot() || process.cwd());
|
|
109
|
+
break;
|
|
110
|
+
|
|
86
111
|
case "opera": {
|
|
87
112
|
const opera = require("../lib/opera");
|
|
88
113
|
const sub = args[0];
|
|
89
|
-
const root = config.resolveProjectRoot() || process.cwd();
|
|
90
|
-
if (sub === "install") await opera.cmdInstall(root, args.slice(1));
|
|
91
|
-
else if (sub === "bootstrap") await opera.cmdBootstrap(root, args.slice(1));
|
|
92
|
-
else if (sub === "
|
|
93
|
-
else if (sub === "
|
|
94
|
-
else if (sub === "
|
|
95
|
-
else
|
|
96
|
-
|
|
97
|
-
|
|
114
|
+
const root = config.resolveProjectRoot() || process.cwd();
|
|
115
|
+
if (sub === "install") await opera.cmdInstall(root, args.slice(1));
|
|
116
|
+
else if (sub === "bootstrap") await opera.cmdBootstrap(root, args.slice(1));
|
|
117
|
+
else if (sub === "handoff") opera.cmdHandoff(root, args.slice(1));
|
|
118
|
+
else if (sub === "status") opera.cmdStatus(root);
|
|
119
|
+
else if (sub === "configure") opera.cmdConfigure(root, args.slice(1));
|
|
120
|
+
else if (sub === "upgrade") opera.cmdUpgrade(root, args.slice(1));
|
|
121
|
+
else { console.log(t("cli.usage.opera")); }
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
98
124
|
|
|
99
125
|
case "skill": {
|
|
100
126
|
const skills = require("../lib/skills");
|
|
@@ -104,7 +130,7 @@ async function run() {
|
|
|
104
130
|
else if (sub === "list") skills.cmdList(root);
|
|
105
131
|
else if (sub === "remove") skills.cmdRemove(root, args[1]);
|
|
106
132
|
else if (sub === "catalog") skills.cmdCatalog();
|
|
107
|
-
else { console.log("
|
|
133
|
+
else { console.log(t("cli.usage.skill")); }
|
|
108
134
|
break;
|
|
109
135
|
}
|
|
110
136
|
|
|
@@ -118,14 +144,14 @@ async function run() {
|
|
|
118
144
|
case "--help":
|
|
119
145
|
case "-h":
|
|
120
146
|
case undefined:
|
|
121
|
-
require("../lib/control").cmdHelp();
|
|
122
|
-
break;
|
|
123
|
-
|
|
124
|
-
default:
|
|
125
|
-
console.error(
|
|
126
|
-
console.error("
|
|
127
|
-
process.exit(1);
|
|
128
|
-
}
|
|
147
|
+
require("../lib/control").cmdHelp();
|
|
148
|
+
break;
|
|
149
|
+
|
|
150
|
+
default:
|
|
151
|
+
console.error(t("cli.error.unknownCommand", { command }));
|
|
152
|
+
console.error(t("cli.error.runHelp"));
|
|
153
|
+
process.exit(1);
|
|
154
|
+
}
|
|
129
155
|
} catch (error) {
|
|
130
156
|
console.error(error.message);
|
|
131
157
|
process.exit(1);
|
package/lib/config.js
CHANGED
|
@@ -86,8 +86,15 @@ function createSplitContext(workspaceRoot, manifest = {}) {
|
|
|
86
86
|
taskPlan: path.join(opsRoot, "task_plan.md"),
|
|
87
87
|
progress: path.join(opsRoot, "progress.md"),
|
|
88
88
|
findings: path.join(opsRoot, "findings.md"),
|
|
89
|
+
architectureDir: path.join(opsRoot, "architecture"),
|
|
89
90
|
hooksDir: path.join(opsRoot, ".githooks"),
|
|
90
91
|
tmpDir: path.join(opsRoot, ".tmp"),
|
|
92
|
+
bootstrapDir: path.join(opsRoot, "bootstrap"),
|
|
93
|
+
contractDir: path.join(opsRoot, "contract"),
|
|
94
|
+
contractFile: path.join(opsRoot, "contract", "operating-contract.json"),
|
|
95
|
+
policyDir: path.join(opsRoot, "policy"),
|
|
96
|
+
autonomyPolicyFile: path.join(opsRoot, "policy", "autonomy.json"),
|
|
97
|
+
reviewsDir: path.join(opsRoot, "reviews"),
|
|
91
98
|
skillsDir: path.join(opsRoot, ".agents", "skills"),
|
|
92
99
|
registryPath: path.join(opsRoot, ".agents", "skills", "_registry.md"),
|
|
93
100
|
agentHubDir: path.join(opsRoot, ".agent", "hub"),
|
|
@@ -137,8 +144,15 @@ function createLegacyContext(rootDir) {
|
|
|
137
144
|
taskPlan: path.join(root, "task_plan.md"),
|
|
138
145
|
progress: path.join(root, "progress.md"),
|
|
139
146
|
findings: path.join(root, "findings.md"),
|
|
147
|
+
architectureDir: path.join(root, "architecture"),
|
|
140
148
|
hooksDir: path.join(root, ".githooks"),
|
|
141
149
|
tmpDir: path.join(root, ".tmp"),
|
|
150
|
+
bootstrapDir: path.join(root, "bootstrap"),
|
|
151
|
+
contractDir: path.join(root, "contract"),
|
|
152
|
+
contractFile: path.join(root, "contract", "operating-contract.json"),
|
|
153
|
+
policyDir: path.join(root, "policy"),
|
|
154
|
+
autonomyPolicyFile: path.join(root, "policy", "autonomy.json"),
|
|
155
|
+
reviewsDir: path.join(root, "reviews"),
|
|
142
156
|
skillsDir: path.join(root, ".agents", "skills"),
|
|
143
157
|
registryPath: path.join(root, ".agents", "skills", "_registry.md"),
|
|
144
158
|
agentHubDir: path.join(root, ".agent", "hub"),
|
|
@@ -255,14 +269,6 @@ function getOperaVersion(control) {
|
|
|
255
269
|
return control.meta?.opera?.version || null;
|
|
256
270
|
}
|
|
257
271
|
|
|
258
|
-
function isEtapaInstalled(control) {
|
|
259
|
-
return isOperaInstalled(control);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
function getEtapaVersion(control) {
|
|
263
|
-
return getOperaVersion(control);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
272
|
function loadControl(contextOrRoot) {
|
|
267
273
|
const filePath = controlFilePath(contextOrRoot);
|
|
268
274
|
return JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
@@ -315,8 +321,6 @@ module.exports = {
|
|
|
315
321
|
getLocale,
|
|
316
322
|
isOperaInstalled,
|
|
317
323
|
getOperaVersion,
|
|
318
|
-
isEtapaInstalled,
|
|
319
|
-
getEtapaVersion,
|
|
320
324
|
loadControl,
|
|
321
325
|
saveControl,
|
|
322
326
|
};
|
package/lib/control.js
CHANGED
|
@@ -442,6 +442,12 @@ function cmdStatus(root) {
|
|
|
442
442
|
}
|
|
443
443
|
if (control.meta?.opera?.bootstrap?.status) {
|
|
444
444
|
console.log(t("cli.status.bootstrap", { status: control.meta.opera.bootstrap.status, locale: config.getLocale(control) }));
|
|
445
|
+
if (control.meta.opera.bootstrap.mode) {
|
|
446
|
+
console.log(`Bootstrap mode: ${control.meta.opera.bootstrap.mode}`);
|
|
447
|
+
}
|
|
448
|
+
if (control.meta.opera.bootstrap.routeReason) {
|
|
449
|
+
console.log(`Bootstrap route: ${control.meta.opera.bootstrap.routeReason}`);
|
|
450
|
+
}
|
|
445
451
|
}
|
|
446
452
|
console.log(t("cli.status.tasks", {
|
|
447
453
|
completed: state.totals.completed, inProgress: state.totals.inProgress,
|
|
@@ -541,51 +547,57 @@ function cmdInstallHooks(root) {
|
|
|
541
547
|
}
|
|
542
548
|
|
|
543
549
|
function cmdHelp() {
|
|
544
|
-
console.log(
|
|
550
|
+
console.log(`trackops — ${t("cli.help.title")}`);
|
|
545
551
|
console.log("");
|
|
546
|
-
console.log("
|
|
552
|
+
console.log(`${t("cli.help.usage")} trackops <command> [args]`);
|
|
547
553
|
console.log("");
|
|
548
|
-
console.log("
|
|
554
|
+
console.log(t("cli.help.commands"));
|
|
549
555
|
console.log(" init [--with-opera] [--legacy-layout] [--locale es|en] [--name \"...\"] [--no-bootstrap]");
|
|
550
|
-
console.log("
|
|
551
|
-
console.log("
|
|
556
|
+
console.log(" [--bootstrap-mode auto|direct|handoff] [--technical-level low|medium|high|senior]");
|
|
557
|
+
console.log(" [--project-state idea|draft|existing_repo|advanced] [--docs-state none|notes|sos|spec_dossier|repo_docs]");
|
|
558
|
+
console.log(" [--decision-ownership user|shared|agent]");
|
|
559
|
+
console.log(` ${t("cli.help.init.desc")}`);
|
|
552
560
|
console.log(" workspace status|migrate");
|
|
553
|
-
console.log("
|
|
561
|
+
console.log(` ${t("cli.help.workspace.desc")}`);
|
|
554
562
|
console.log(" env status|sync");
|
|
555
|
-
console.log("
|
|
563
|
+
console.log(` ${t("cli.help.env.desc")}`);
|
|
556
564
|
console.log(" release [--push]");
|
|
557
|
-
console.log("
|
|
565
|
+
console.log(` ${t("cli.help.release.desc")}`);
|
|
558
566
|
console.log(" version");
|
|
559
|
-
console.log("
|
|
567
|
+
console.log(` ${t("cli.help.version.desc")}`);
|
|
560
568
|
console.log(" status");
|
|
561
|
-
console.log("
|
|
562
|
-
console.log(" next");
|
|
563
|
-
console.log("
|
|
564
|
-
console.log(" sync");
|
|
565
|
-
console.log("
|
|
566
|
-
console.log(" dashboard [--port N] [--host HOST] [--public] [--strict-port]");
|
|
567
|
-
console.log("
|
|
569
|
+
console.log(` ${t("cli.help.status.desc")}`);
|
|
570
|
+
console.log(" next");
|
|
571
|
+
console.log(` ${t("cli.help.next.desc")}`);
|
|
572
|
+
console.log(" sync");
|
|
573
|
+
console.log(` ${t("cli.help.sync.desc")}`);
|
|
574
|
+
console.log(" dashboard [--port N] [--host HOST] [--public] [--strict-port]");
|
|
575
|
+
console.log(` ${t("cli.help.dashboard.desc")}`);
|
|
568
576
|
console.log(" refresh-repo [--quiet]");
|
|
569
|
-
console.log("
|
|
577
|
+
console.log(` ${t("cli.help.refreshRepo.desc")}`);
|
|
570
578
|
console.log(" install-hooks");
|
|
571
|
-
console.log("
|
|
572
|
-
console.log(" register");
|
|
573
|
-
console.log("
|
|
574
|
-
console.log(" projects");
|
|
575
|
-
console.log("
|
|
576
|
-
console.log(" task <action> <id> [note]");
|
|
577
|
-
console.log("
|
|
578
|
-
console.log(" opera install|bootstrap|status|configure|upgrade");
|
|
579
|
-
console.log("
|
|
579
|
+
console.log(` ${t("cli.help.installHooks.desc")}`);
|
|
580
|
+
console.log(" register");
|
|
581
|
+
console.log(` ${t("cli.help.register.desc")}`);
|
|
582
|
+
console.log(" projects");
|
|
583
|
+
console.log(` ${t("cli.help.projects.desc")}`);
|
|
584
|
+
console.log(" task <action> <id> [note]");
|
|
585
|
+
console.log(` ${t("cli.help.task.desc")}`);
|
|
586
|
+
console.log(" opera install|bootstrap|handoff|status|configure|upgrade");
|
|
587
|
+
console.log(` ${t("cli.help.opera.desc")}`);
|
|
588
|
+
console.log(` ${t("cli.help.opera.upgradeHint")}`);
|
|
589
|
+
console.log(" locale get|set [es|en]");
|
|
590
|
+
console.log(` ${t("cli.help.locale.desc")}`);
|
|
591
|
+
console.log(" doctor locale");
|
|
592
|
+
console.log(` ${t("cli.help.doctor.desc")}`);
|
|
580
593
|
console.log(" skill install|list|remove|catalog <name>");
|
|
581
|
-
console.log("
|
|
594
|
+
console.log(` ${t("cli.help.skill.desc")}`);
|
|
582
595
|
console.log(" help");
|
|
583
|
-
console.log("
|
|
596
|
+
console.log(` ${t("cli.help.help.desc")}`);
|
|
584
597
|
console.log("");
|
|
585
|
-
console.log("
|
|
586
|
-
console.log(
|
|
587
|
-
console.log(
|
|
588
|
-
console.log(" 'trackops opera install' explicitly inside each project you want to manage.");
|
|
598
|
+
console.log(t("cli.help.globalWorkflow"));
|
|
599
|
+
console.log(` ${t("cli.help.globalWorkflow.line1")}`);
|
|
600
|
+
console.log(` ${t("cli.help.globalWorkflow.line2")}`);
|
|
589
601
|
}
|
|
590
602
|
|
|
591
603
|
/* ── project-scoped API (used by server) ── */
|
package/lib/env.js
CHANGED
|
@@ -59,8 +59,13 @@ function normalizeEnvironmentMeta(control, context) {
|
|
|
59
59
|
function inferRequiredKeys(control, contextOrRoot) {
|
|
60
60
|
const envMeta = control.meta?.environment || {};
|
|
61
61
|
const fromMeta = unique([...(envMeta.requiredKeys || []), ...(envMeta.optionalKeys || [])]);
|
|
62
|
+
const contractServices = readContractServices(contextOrRoot, control);
|
|
63
|
+
const bootstrapServices = unique([
|
|
64
|
+
...(control.meta?.opera?.bootstrap?.discovery?.externalServices || []),
|
|
65
|
+
...(control.meta?.opera?.bootstrap?.externalServices || []),
|
|
66
|
+
]);
|
|
62
67
|
const fromServices = unique(
|
|
63
|
-
(
|
|
68
|
+
(contractServices.length ? contractServices : bootstrapServices)
|
|
64
69
|
.flatMap((service) => SERVICE_ENV_KEYS[service] || []),
|
|
65
70
|
);
|
|
66
71
|
const context = config.ensureContext(contextOrRoot || process.cwd());
|
|
@@ -68,6 +73,18 @@ function inferRequiredKeys(control, contextOrRoot) {
|
|
|
68
73
|
return unique([...fromMeta, ...fromServices, ...fromExample]);
|
|
69
74
|
}
|
|
70
75
|
|
|
76
|
+
function readContractServices(contextOrRoot, control) {
|
|
77
|
+
const context = config.ensureContext(contextOrRoot || process.cwd());
|
|
78
|
+
const contractFile = context.paths.contractFile;
|
|
79
|
+
if (!fs.existsSync(contractFile)) return [];
|
|
80
|
+
try {
|
|
81
|
+
const contract = JSON.parse(fs.readFileSync(contractFile, "utf8"));
|
|
82
|
+
return Array.isArray(contract?.system?.externalServices) ? contract.system.externalServices : [];
|
|
83
|
+
} catch (_error) {
|
|
84
|
+
return [];
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
71
88
|
function ensureFileWithHeader(filePath, lines) {
|
|
72
89
|
if (fs.existsSync(filePath)) return;
|
|
73
90
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
package/lib/init.js
CHANGED
|
@@ -10,6 +10,7 @@ const env = require("./env");
|
|
|
10
10
|
const workspace = require("./workspace");
|
|
11
11
|
const { t, setLocale } = require("./i18n");
|
|
12
12
|
const { detectSystemLocale, promptForLocale, resolveLocale } = require("./locale");
|
|
13
|
+
const runtimeState = require("./runtime-state");
|
|
13
14
|
|
|
14
15
|
const GENERATED_SCRIPT_COMMANDS = {
|
|
15
16
|
ops: "npx --yes trackops",
|
|
@@ -33,13 +34,23 @@ function parseArgs(args) {
|
|
|
33
34
|
phases: null,
|
|
34
35
|
noBootstrap: false,
|
|
35
36
|
legacyLayout: false,
|
|
37
|
+
bootstrapMode: "auto",
|
|
38
|
+
technicalLevel: null,
|
|
39
|
+
projectState: null,
|
|
40
|
+
docsState: null,
|
|
41
|
+
decisionOwnership: null,
|
|
36
42
|
};
|
|
37
43
|
for (let i = 0; i < args.length; i += 1) {
|
|
38
44
|
if (args[i] === "--locale" && args[i + 1]) { options.locale = args[i + 1]; i += 1; }
|
|
39
45
|
else if (args[i] === "--name" && args[i + 1]) { options.name = args[i + 1]; i += 1; }
|
|
40
|
-
else if (args[i] === "--with-opera"
|
|
46
|
+
else if (args[i] === "--with-opera") { options.withOpera = true; }
|
|
41
47
|
else if (args[i] === "--no-bootstrap") { options.noBootstrap = true; }
|
|
42
48
|
else if (args[i] === "--legacy-layout") { options.legacyLayout = true; }
|
|
49
|
+
else if (args[i] === "--bootstrap-mode" && args[i + 1]) { options.bootstrapMode = args[i + 1]; i += 1; }
|
|
50
|
+
else if (args[i] === "--technical-level" && args[i + 1]) { options.technicalLevel = args[i + 1]; i += 1; }
|
|
51
|
+
else if (args[i] === "--project-state" && args[i + 1]) { options.projectState = args[i + 1]; i += 1; }
|
|
52
|
+
else if (args[i] === "--docs-state" && args[i + 1]) { options.docsState = args[i + 1]; i += 1; }
|
|
53
|
+
else if (args[i] === "--decision-ownership" && args[i + 1]) { options.decisionOwnership = args[i + 1]; i += 1; }
|
|
43
54
|
else if (args[i] === "--phases" && args[i + 1]) {
|
|
44
55
|
try { options.phases = JSON.parse(args[i + 1]); } catch (_e) { /* ignore */ }
|
|
45
56
|
i += 1;
|
|
@@ -62,7 +73,7 @@ function detectProjectName(root) {
|
|
|
62
73
|
}
|
|
63
74
|
|
|
64
75
|
function buildDefaultControl(context, options) {
|
|
65
|
-
const locale = resolveLocale(options.locale, config.DEFAULT_LOCALE);
|
|
76
|
+
const locale = resolveLocale(options.locale, runtimeState.getGlobalLocale() || config.DEFAULT_LOCALE);
|
|
66
77
|
const phases = options.phases || config.buildDefaultPhases(locale);
|
|
67
78
|
const isSplit = context.layout === "split";
|
|
68
79
|
setLocale(locale);
|
|
@@ -96,6 +107,16 @@ function buildDefaultControl(context, options) {
|
|
|
96
107
|
optionalKeys: [],
|
|
97
108
|
lastAuditAt: null,
|
|
98
109
|
},
|
|
110
|
+
userProfile: {
|
|
111
|
+
technicalLevel: null,
|
|
112
|
+
explanationMode: null,
|
|
113
|
+
capturedAt: null,
|
|
114
|
+
},
|
|
115
|
+
discovery: {
|
|
116
|
+
projectState: null,
|
|
117
|
+
documentationState: null,
|
|
118
|
+
availableArtifacts: [],
|
|
119
|
+
},
|
|
99
120
|
},
|
|
100
121
|
checks: {
|
|
101
122
|
lastBuild: { status: "pending", date: null, note: "" },
|
|
@@ -188,7 +209,7 @@ function initSplitProject(root, options) {
|
|
|
188
209
|
workspace.ensureRootGitignore(targetRoot);
|
|
189
210
|
|
|
190
211
|
const control = buildDefaultControl(context, options);
|
|
191
|
-
control.meta.projectName = options.name || detectProjectName(context.
|
|
212
|
+
control.meta.projectName = options.name || detectProjectName(context.workspaceRoot);
|
|
192
213
|
config.saveControl(context, control);
|
|
193
214
|
|
|
194
215
|
installHooks(context);
|
|
@@ -261,7 +282,7 @@ function initLegacyProject(root, options) {
|
|
|
261
282
|
|
|
262
283
|
function initProject(root, options) {
|
|
263
284
|
const normalized = { ...(options || {}) };
|
|
264
|
-
normalized.locale = resolveLocale(normalized.locale, config.DEFAULT_LOCALE);
|
|
285
|
+
normalized.locale = resolveLocale(normalized.locale, runtimeState.getGlobalLocale() || config.DEFAULT_LOCALE);
|
|
265
286
|
setLocale(normalized.locale);
|
|
266
287
|
if (normalized.legacyLayout) {
|
|
267
288
|
return initLegacyProject(root, normalized);
|
|
@@ -271,9 +292,17 @@ function initProject(root, options) {
|
|
|
271
292
|
|
|
272
293
|
async function cmdInit(args) {
|
|
273
294
|
const options = parseArgs(args || []);
|
|
274
|
-
|
|
275
|
-
|
|
295
|
+
const explicitLocale = resolveLocale(options.locale, null);
|
|
296
|
+
const globalLocale = runtimeState.getGlobalLocale();
|
|
297
|
+
if (explicitLocale) {
|
|
298
|
+
options.locale = explicitLocale;
|
|
299
|
+
} else if (!globalLocale) {
|
|
276
300
|
options.locale = await promptForLocale(detectSystemLocale());
|
|
301
|
+
} else {
|
|
302
|
+
options.locale = globalLocale;
|
|
303
|
+
}
|
|
304
|
+
if (!globalLocale) {
|
|
305
|
+
await runtimeState.ensureGlobalLocale({ preferredLocale: options.locale, interactive: false });
|
|
277
306
|
}
|
|
278
307
|
setLocale(options.locale || config.DEFAULT_LOCALE);
|
|
279
308
|
|
|
@@ -284,6 +313,11 @@ async function cmdInit(args) {
|
|
|
284
313
|
await opera.install(result.root, {
|
|
285
314
|
locale: options.locale,
|
|
286
315
|
bootstrap: !options.noBootstrap,
|
|
316
|
+
bootstrapMode: options.bootstrapMode,
|
|
317
|
+
technicalLevel: options.technicalLevel,
|
|
318
|
+
projectState: options.projectState,
|
|
319
|
+
docsState: options.docsState,
|
|
320
|
+
decisionOwnership: options.decisionOwnership,
|
|
287
321
|
});
|
|
288
322
|
}
|
|
289
323
|
}
|