@horizon36596/zenith-cli 0.1.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.
Files changed (104) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +18 -0
  3. package/README.md +207 -0
  4. package/dist/autoLoad.d.ts +54 -0
  5. package/dist/autoLoad.d.ts.map +1 -0
  6. package/dist/autoLoad.js +139 -0
  7. package/dist/autoLoad.js.map +1 -0
  8. package/dist/calibrateFit.d.ts +38 -0
  9. package/dist/calibrateFit.d.ts.map +1 -0
  10. package/dist/calibrateFit.js +69 -0
  11. package/dist/calibrateFit.js.map +1 -0
  12. package/dist/commandLibrary.d.ts +19 -0
  13. package/dist/commandLibrary.d.ts.map +1 -0
  14. package/dist/commandLibrary.js +27 -0
  15. package/dist/commandLibrary.js.map +1 -0
  16. package/dist/commands/calibrate.d.ts +18 -0
  17. package/dist/commands/calibrate.d.ts.map +1 -0
  18. package/dist/commands/calibrate.js +116 -0
  19. package/dist/commands/calibrate.js.map +1 -0
  20. package/dist/commands/codegen.d.ts +12 -0
  21. package/dist/commands/codegen.d.ts.map +1 -0
  22. package/dist/commands/codegen.js +63 -0
  23. package/dist/commands/codegen.js.map +1 -0
  24. package/dist/commands/deploy.d.ts +63 -0
  25. package/dist/commands/deploy.d.ts.map +1 -0
  26. package/dist/commands/deploy.js +181 -0
  27. package/dist/commands/deploy.js.map +1 -0
  28. package/dist/commands/diff.d.ts +11 -0
  29. package/dist/commands/diff.d.ts.map +1 -0
  30. package/dist/commands/diff.js +68 -0
  31. package/dist/commands/diff.js.map +1 -0
  32. package/dist/commands/estimate.d.ts +9 -0
  33. package/dist/commands/estimate.d.ts.map +1 -0
  34. package/dist/commands/estimate.js +81 -0
  35. package/dist/commands/estimate.js.map +1 -0
  36. package/dist/commands/init.d.ts +10 -0
  37. package/dist/commands/init.d.ts.map +1 -0
  38. package/dist/commands/init.js +67 -0
  39. package/dist/commands/init.js.map +1 -0
  40. package/dist/commands/new.d.ts +10 -0
  41. package/dist/commands/new.d.ts.map +1 -0
  42. package/dist/commands/new.js +28 -0
  43. package/dist/commands/new.js.map +1 -0
  44. package/dist/commands/propose.d.ts +15 -0
  45. package/dist/commands/propose.d.ts.map +1 -0
  46. package/dist/commands/propose.js +67 -0
  47. package/dist/commands/propose.js.map +1 -0
  48. package/dist/commands/render.d.ts +16 -0
  49. package/dist/commands/render.d.ts.map +1 -0
  50. package/dist/commands/render.js +90 -0
  51. package/dist/commands/render.js.map +1 -0
  52. package/dist/commands/sim.d.ts +31 -0
  53. package/dist/commands/sim.d.ts.map +1 -0
  54. package/dist/commands/sim.js +213 -0
  55. package/dist/commands/sim.js.map +1 -0
  56. package/dist/commands/validate.d.ts +19 -0
  57. package/dist/commands/validate.d.ts.map +1 -0
  58. package/dist/commands/validate.js +97 -0
  59. package/dist/commands/validate.js.map +1 -0
  60. package/dist/coreGate.d.ts +19 -0
  61. package/dist/coreGate.d.ts.map +1 -0
  62. package/dist/coreGate.js +23 -0
  63. package/dist/coreGate.js.map +1 -0
  64. package/dist/fieldImage.d.ts +19 -0
  65. package/dist/fieldImage.d.ts.map +1 -0
  66. package/dist/fieldImage.js +63 -0
  67. package/dist/fieldImage.js.map +1 -0
  68. package/dist/findings.d.ts +20 -0
  69. package/dist/findings.d.ts.map +1 -0
  70. package/dist/findings.js +57 -0
  71. package/dist/findings.js.map +1 -0
  72. package/dist/index.d.ts +32 -0
  73. package/dist/index.d.ts.map +1 -0
  74. package/dist/index.js +194 -0
  75. package/dist/index.js.map +1 -0
  76. package/dist/javaCodegen.d.ts +44 -0
  77. package/dist/javaCodegen.d.ts.map +1 -0
  78. package/dist/javaCodegen.js +537 -0
  79. package/dist/javaCodegen.js.map +1 -0
  80. package/dist/launcher.d.ts +39 -0
  81. package/dist/launcher.d.ts.map +1 -0
  82. package/dist/launcher.js +153 -0
  83. package/dist/launcher.js.map +1 -0
  84. package/dist/lib.d.ts +13 -0
  85. package/dist/lib.d.ts.map +1 -0
  86. package/dist/lib.js +13 -0
  87. package/dist/lib.js.map +1 -0
  88. package/dist/project.d.ts +33 -0
  89. package/dist/project.d.ts.map +1 -0
  90. package/dist/project.js +104 -0
  91. package/dist/project.js.map +1 -0
  92. package/dist/skeletons.d.ts +16 -0
  93. package/dist/skeletons.d.ts.map +1 -0
  94. package/dist/skeletons.js +120 -0
  95. package/dist/skeletons.js.map +1 -0
  96. package/dist/traceReport.d.ts +75 -0
  97. package/dist/traceReport.d.ts.map +1 -0
  98. package/dist/traceReport.js +91 -0
  99. package/dist/traceReport.js.map +1 -0
  100. package/dist/version.d.ts +3 -0
  101. package/dist/version.d.ts.map +1 -0
  102. package/dist/version.js +4 -0
  103. package/dist/version.js.map +1 -0
  104. package/package.json +71 -0
@@ -0,0 +1,18 @@
1
+ export interface CalibrateOptions {
2
+ cwd?: string;
3
+ project?: string;
4
+ json?: boolean;
5
+ traces?: string;
6
+ write?: boolean;
7
+ /** Overrides the provenance date; the CLI reads the clock, `core` never does (CLAUDE.md rule 1). */
8
+ date?: string;
9
+ }
10
+ /**
11
+ * `zenith calibrate [--traces <dir>] [--write]`: fits `accel`, `settleS` and a per heading-mode
12
+ * scale against every trace it can find (site/docs/simulation.md).
13
+ * `--write` updates the two existing `robot.json.kinematics` fields the schema already has
14
+ * (`accelInPerS2`, `settleS`); the per-mode scale has no field there yet (`@horizon36596/zenith-schema` is not
15
+ * this package's to extend), so it is reported but not persisted.
16
+ */
17
+ export declare function runCalibrate(options: CalibrateOptions): number;
18
+ //# sourceMappingURL=calibrate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calibrate.d.ts","sourceRoot":"","sources":["../../src/commands/calibrate.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,gBAAgB;IAC/B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,oGAAoG;IACpG,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAkBD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CA8F9D"}
@@ -0,0 +1,116 @@
1
+ import { existsSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { canonicalize, flattenSteps } from "@horizon36596/zenith-core";
4
+ import { parseRobot } from "@horizon36596/zenith-schema";
5
+ import { loadAutoAndPlan } from "../autoLoad.js";
6
+ import { fitCalibration } from "../calibrateFit.js";
7
+ import { loadProject, ProjectError, readJsonFile } from "../project.js";
8
+ import { parseTrace } from "../traceReport.js";
9
+ /** `TeamCode/build/sim/{auto}.trace.json` -> `TeamCode/build/sim`. `null` when the template has no
10
+ * directory part to strip, so the caller falls back to something else. */
11
+ function traceDirFromTemplate(template) {
12
+ const slash = template.lastIndexOf("/");
13
+ return slash === -1 ? null : template.slice(0, slash);
14
+ }
15
+ function defaultTracesDir(project) {
16
+ if (existsSync(join(project.root, "traces")))
17
+ return "traces";
18
+ return project.link.sim === undefined ? null : traceDirFromTemplate(project.link.sim.trace);
19
+ }
20
+ function isRecord(value) {
21
+ return typeof value === "object" && value !== null && !Array.isArray(value);
22
+ }
23
+ /**
24
+ * `zenith calibrate [--traces <dir>] [--write]`: fits `accel`, `settleS` and a per heading-mode
25
+ * scale against every trace it can find (site/docs/simulation.md).
26
+ * `--write` updates the two existing `robot.json.kinematics` fields the schema already has
27
+ * (`accelInPerS2`, `settleS`); the per-mode scale has no field there yet (`@horizon36596/zenith-schema` is not
28
+ * this package's to extend), so it is reported but not persisted.
29
+ */
30
+ export function runCalibrate(options) {
31
+ const cwd = options.cwd ?? process.cwd();
32
+ const project = loadProject(cwd, options.project);
33
+ const tracesDirRel = options.traces ?? defaultTracesDir(project);
34
+ if (tracesDirRel === null) {
35
+ throw new ProjectError("no traces directory to calibrate from: pass --traces <dir>, commit a traces/ directory, or set zenith.json's sim.trace.");
36
+ }
37
+ const tracesDirFull = join(project.root, tracesDirRel);
38
+ if (!existsSync(tracesDirFull))
39
+ throw new ProjectError(`no such directory: ${tracesDirRel}`);
40
+ const traceFileNames = readdirSync(tracesDirFull).filter((name) => name.endsWith(".trace.json")).sort();
41
+ const samples = [];
42
+ const usedTraces = [];
43
+ const skipped = [];
44
+ for (const fileName of traceFileNames) {
45
+ let trace;
46
+ try {
47
+ trace = parseTrace(JSON.parse(readFileSync(join(tracesDirFull, fileName), "utf8")));
48
+ }
49
+ catch (error) {
50
+ skipped.push({ file: fileName, reason: error instanceof Error ? error.message : String(error) });
51
+ continue;
52
+ }
53
+ const autoPath = join(project.root, project.link.autosDir, `${trace.auto}.auto.json`);
54
+ if (!existsSync(autoPath)) {
55
+ skipped.push({ file: fileName, reason: `no ${trace.auto}.auto.json in ${project.link.autosDir}` });
56
+ continue;
57
+ }
58
+ const loaded = loadAutoAndPlan(autoPath, project);
59
+ if (!loaded.ok) {
60
+ skipped.push({ file: fileName, reason: `${trace.auto}.auto.json does not load` });
61
+ continue;
62
+ }
63
+ const planSteps = flattenSteps(loaded.loaded.plan.steps);
64
+ let matched = 0;
65
+ for (const traceStep of trace.steps) {
66
+ const planStep = planSteps.find((candidate) => candidate.id === traceStep.id);
67
+ if (planStep === undefined || planStep.kind !== "path")
68
+ continue;
69
+ const heading = planStep.step.heading?.mode ?? "none";
70
+ samples.push({
71
+ stepId: traceStep.id,
72
+ headingMode: heading,
73
+ lengthIn: planStep.lengthIn,
74
+ actualS: traceStep.endS - traceStep.startS,
75
+ });
76
+ matched += 1;
77
+ }
78
+ if (matched > 0)
79
+ usedTraces.push(fileName);
80
+ }
81
+ const fit = fitCalibration(samples, project.robot.kinematics.maxForwardVelInPerS.value);
82
+ let written = null;
83
+ if (options.write === true && fit.sampleCount > 0) {
84
+ const date = options.date ?? new Date().toISOString().slice(0, 10);
85
+ const provenance = `CALIBRATED FROM SIM ${date} (${String(fit.sampleCount)} steps)`;
86
+ const robotRelative = project.link.robot;
87
+ const robotFull = join(project.root, robotRelative);
88
+ const raw = readJsonFile(robotFull);
89
+ if (!isRecord(raw) || !isRecord(raw.kinematics)) {
90
+ throw new ProjectError(`${robotRelative} has no "kinematics" object to write the calibration into.`);
91
+ }
92
+ raw.kinematics.accelInPerS2 = { value: Number(fit.accelInPerS2.toFixed(4)), provenance };
93
+ raw.kinematics.settleS = { value: Number(fit.settleS.toFixed(4)), provenance };
94
+ writeFileSync(robotFull, canonicalize("robot", parseRobot(raw)), "utf8");
95
+ written = robotRelative;
96
+ }
97
+ if (options.json === true) {
98
+ process.stdout.write(`${JSON.stringify({ tracesDir: tracesDirRel, usedTraces, skipped, fit, written }, null, 2)}\n`);
99
+ return 0;
100
+ }
101
+ process.stdout.write(`traces: ${tracesDirRel} (${String(usedTraces.length)} used, ${String(skipped.length)} skipped)\n`);
102
+ if (fit.sampleCount === 0) {
103
+ process.stdout.write("no path-step samples to fit; nothing was written.\n");
104
+ return 0;
105
+ }
106
+ process.stdout.write(`accelInPerS2: ${fit.accelInPerS2.toFixed(2)}\n`);
107
+ process.stdout.write(`settleS: ${fit.settleS.toFixed(3)}\n`);
108
+ process.stdout.write("scale by heading mode (reported, not written - robot.json has no field for it yet):\n");
109
+ for (const [mode, scale] of Object.entries(fit.scaleByMode)) {
110
+ process.stdout.write(` ${mode}: ${scale.toFixed(3)}\n`);
111
+ }
112
+ process.stdout.write(`residual band: ${(fit.residualLowFraction * 100).toFixed(0)}% to +${(fit.residualHighFraction * 100).toFixed(0)}% (${String(fit.sampleCount)} steps)\n`);
113
+ process.stdout.write(written === null ? "not written (pass --write)\n" : `written: ${written}\n`);
114
+ return 0;
115
+ }
116
+ //# sourceMappingURL=calibrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calibrate.js","sourceRoot":"","sources":["../../src/commands/calibrate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export interface CodegenOptions {
2
+ cwd?: string;
3
+ project?: string;
4
+ json?: boolean;
5
+ }
6
+ /**
7
+ * `zenith codegen <auto>`: the readable, derived `AutoFromFile` subclass of
8
+ * site/docs/robot-runtime.md. Needs only schema and M0's `check()`, so it
9
+ * does not wait on M1's estimator or ledger.
10
+ */
11
+ export declare function runCodegen(autoArg: string, options: CodegenOptions): number;
12
+ //# sourceMappingURL=codegen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../../src/commands/codegen.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAID;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,MAAM,CAsD3E"}
@@ -0,0 +1,63 @@
1
+ import { createHash } from "node:crypto";
2
+ import { mkdirSync, writeFileSync } from "node:fs";
3
+ import { dirname, join, relative } from "node:path";
4
+ import { canonicalize } from "@horizon36596/zenith-core";
5
+ import { loadAutoAndPlan, resolveAutoPath } from "../autoLoad.js";
6
+ import { countErrors, formatFindingsTable } from "../findings.js";
7
+ import { commandLibraryOf } from "../commandLibrary.js";
8
+ import { generateAutoJava, pascalCase } from "../javaCodegen.js";
9
+ import { loadProject, ProjectError } from "../project.js";
10
+ const slash = (path) => path.split("\\").join("/");
11
+ /**
12
+ * `zenith codegen <auto>`: the readable, derived `AutoFromFile` subclass of
13
+ * site/docs/robot-runtime.md. Needs only schema and M0's `check()`, so it
14
+ * does not wait on M1's estimator or ledger.
15
+ */
16
+ export function runCodegen(autoArg, options) {
17
+ const cwd = options.cwd ?? process.cwd();
18
+ const project = loadProject(cwd, options.project, autoArg);
19
+ const path = resolveAutoPath(cwd, project, autoArg);
20
+ const relPath = slash(relative(project.root, path));
21
+ const result = loadAutoAndPlan(path, project);
22
+ const findings = result.ok ? result.loaded.findings : result.findings;
23
+ const files = [{ path: relPath, findings }];
24
+ if (countErrors(files) > 0) {
25
+ if (options.json === true) {
26
+ process.stdout.write(`${JSON.stringify({ project: slash(project.root), files, errors: countErrors(files) }, null, 2)}\n`);
27
+ }
28
+ else {
29
+ process.stdout.write(`${formatFindingsTable(files)}\n`);
30
+ }
31
+ return 1;
32
+ }
33
+ if (!result.ok) {
34
+ // Unreachable given countErrors gated above, but keeps the type narrowing honest.
35
+ return 1;
36
+ }
37
+ const codegenConfig = project.link.codegen;
38
+ if (codegenConfig === undefined) {
39
+ throw new ProjectError('zenith.json has no "codegen" section (package and dir); add one before running zenith codegen.');
40
+ }
41
+ const canonicalBytes = canonicalize("auto", result.loaded.auto);
42
+ const shaHex = createHash("sha256").update(canonicalBytes, "utf8").digest("hex").slice(0, 8);
43
+ const packagePath = codegenConfig.package.split(".").join("/");
44
+ const fileName = `${pascalCase(result.loaded.auto.name)}Generated.java`;
45
+ const outRelative = join(codegenConfig.dir, packagePath, fileName);
46
+ const outFull = join(project.root, outRelative);
47
+ const java = generateAutoJava(result.loaded.plan, {
48
+ packageName: codegenConfig.package,
49
+ shaHex,
50
+ sourcePath: relPath,
51
+ commandLibrary: commandLibraryOf(project.link),
52
+ });
53
+ mkdirSync(dirname(outFull), { recursive: true });
54
+ writeFileSync(outFull, java, "utf8");
55
+ if (options.json === true) {
56
+ process.stdout.write(`${JSON.stringify({ written: slash(outRelative), shaHex }, null, 2)}\n`);
57
+ }
58
+ else {
59
+ process.stdout.write(`written: ${slash(outRelative)}\n`);
60
+ }
61
+ return 0;
62
+ }
63
+ //# sourceMappingURL=codegen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codegen.js","sourceRoot":"","sources":["../../src/commands/codegen.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ import { type CommandLibrary } from "../commandLibrary.js";
2
+ import { type Project } from "../project.js";
3
+ export interface DeployOptions {
4
+ cwd?: string;
5
+ project?: string;
6
+ json?: boolean;
7
+ dryRun?: boolean;
8
+ }
9
+ export type DeployActionKind = "copy" | "write" | "keep" | "remove" | "skip";
10
+ export interface DeployAction {
11
+ kind: DeployActionKind;
12
+ /** The path written, copied to or removed, relative to the project root. */
13
+ path: string;
14
+ /** Where a "copy" came from, relative to the project root. */
15
+ from?: string;
16
+ /** The bytes a "write" puts at `path`. Carried here so applying the plan needs no recomputation. */
17
+ content?: string;
18
+ /** Why a "skip" happened. */
19
+ reason?: string;
20
+ }
21
+ export interface StubOptions {
22
+ packageName: string;
23
+ className: string;
24
+ autoName: string;
25
+ title: string;
26
+ relSource: string;
27
+ /** `zenith.json` `deploy.robotClass`: the team's `ZenithRobot`, fully qualified. */
28
+ robotClass: string;
29
+ /** `zenith.json` `deploy.preselectTeleOp`; the annotation leaves it out when unset. */
30
+ preselectTeleOp?: string;
31
+ /** `zenith.json` `deploy.commandLibrary`: which runtime's classes the stub imports. */
32
+ commandLibrary: CommandLibrary;
33
+ }
34
+ /**
35
+ * One `@Autonomous` OpMode per auto file, extending the published runtime's `AutoFromFile`
36
+ * (robot/README.md): `org.horizon36596.zenith.solverslib.AutoFromFile` for SolversLib, or
37
+ * `org.horizon36596.zenith.ivy.AutoFromFile` for Ivy. It names the file and constructs the team's
38
+ * robot; everything else is the runtime's.
39
+ */
40
+ export declare function autoStub(options: StubOptions): string;
41
+ export interface DeployPlan {
42
+ /**
43
+ * The command library the stubs are written for, from `deploy.commandLibrary`. Undefined only when
44
+ * `zenith.json` has no `codegen` section, so the deploy writes no Java, and names no library.
45
+ */
46
+ commandLibrary: CommandLibrary | undefined;
47
+ actions: DeployAction[];
48
+ /** Autos that failed `check()` and so were not copied or stubbed. */
49
+ errors: number;
50
+ }
51
+ /** Works out every copy, stub write and stale-stub removal, without touching the filesystem. */
52
+ export declare function planDeploy(project: Project): DeployPlan;
53
+ /** Performs the actions `planDeploy` worked out. `keep` and `skip` need nothing done. */
54
+ export declare function applyDeploy(project: Project, plan: DeployPlan): void;
55
+ /**
56
+ * `zenith deploy`: copies every valid auto plus `waypoints.json`, `robot.json` and the field file to
57
+ * `zenith.json.deploy.dir`, and writes or refreshes one `@Autonomous` stub per auto under
58
+ * `codegen.dir/<package>/generated/` (site/docs/robot-runtime.md), removing
59
+ * stubs for autos that no longer exist. The stubs are written only when `zenith.json` has a `codegen`
60
+ * section, and only then is `deploy.commandLibrary` required. `--dry-run` only lists what it would do.
61
+ */
62
+ export declare function runDeploy(options: DeployOptions): number;
63
+ //# sourceMappingURL=deploy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAIA,OAAO,EAAoD,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE7G,OAAO,EAA0C,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AAErF,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE7E,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,gBAAgB,CAAC;IACvB,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAC;IACb,8DAA8D;IAC9D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oGAAoG;IACpG,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6BAA6B;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAID,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,oFAAoF;IACpF,UAAU,EAAE,MAAM,CAAC;IACnB,uFAAuF;IACvF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uFAAuF;IACvF,cAAc,EAAE,cAAc,CAAC;CAChC;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAqBrD;AAED,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,cAAc,EAAE,cAAc,GAAG,SAAS,CAAC;IAC3C,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,gGAAgG;AAChG,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,UAAU,CAoGvD;AAED,yFAAyF;AACzF,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI,CAiBpE;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAkCxD"}
@@ -0,0 +1,181 @@
1
+ import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
2
+ import { basename, dirname, join } from "node:path";
3
+ import { hasErrors } from "@horizon36596/zenith-core";
4
+ import { loadAutoAndPlan } from "../autoLoad.js";
5
+ import { commandLibraryOf, LIBRARY_LABEL, RUNTIME_PACKAGE } from "../commandLibrary.js";
6
+ import { pascalCase } from "../javaCodegen.js";
7
+ import { confinePath, loadProject, ProjectError } from "../project.js";
8
+ const slash = (path) => path.split("\\").join("/");
9
+ /**
10
+ * One `@Autonomous` OpMode per auto file, extending the published runtime's `AutoFromFile`
11
+ * (robot/README.md): `org.horizon36596.zenith.solverslib.AutoFromFile` for SolversLib, or
12
+ * `org.horizon36596.zenith.ivy.AutoFromFile` for Ivy. It names the file and constructs the team's
13
+ * robot; everything else is the runtime's.
14
+ */
15
+ export function autoStub(options) {
16
+ const annotation = [`name = ${JSON.stringify(options.title)}`, `group = "Generated"`];
17
+ if (options.preselectTeleOp !== undefined) {
18
+ annotation.push(`preselectTeleOp = ${JSON.stringify(options.preselectTeleOp)}`);
19
+ }
20
+ const runtime = RUNTIME_PACKAGE[options.commandLibrary];
21
+ return [
22
+ `package ${options.packageName}.generated;`,
23
+ "",
24
+ "import com.qualcomm.robotcore.eventloop.opmode.Autonomous;",
25
+ `import ${runtime}.AutoFromFile;`,
26
+ `import ${runtime}.ZenithRobot;`,
27
+ "",
28
+ `/** GENERATED by zenith deploy from ${options.relSource}. Do not edit; edit the file and re-run zenith deploy. */`,
29
+ `@Autonomous(${annotation.join(", ")})`,
30
+ `public final class ${options.className} extends AutoFromFile {`,
31
+ ` @Override protected String autoName() { return ${JSON.stringify(options.autoName)}; }`,
32
+ ` @Override protected ZenithRobot createRobot() { return new ${options.robotClass}(); }`,
33
+ "}",
34
+ "",
35
+ ].join("\n");
36
+ }
37
+ /** Works out every copy, stub write and stale-stub removal, without touching the filesystem. */
38
+ export function planDeploy(project) {
39
+ const actions = [];
40
+ let errors = 0;
41
+ const link = project.link;
42
+ if (link.deploy === undefined) {
43
+ throw new ProjectError('zenith.json has no "deploy" section; add one before running zenith deploy.');
44
+ }
45
+ // The OpMode stubs are the only Java a deploy writes, and it writes them only when zenith.json has a
46
+ // "codegen" section; the data files it copies name no command library. So the library is required
47
+ // exactly when there is a "codegen" section, and checked before anything else, so a project that has
48
+ // not chosen one learns that first. Without "codegen", a library the file names is still reported.
49
+ const commandLibrary = link.codegen === undefined ? link.deploy.commandLibrary : commandLibraryOf(link);
50
+ const autosDirFull = join(project.root, link.autosDir);
51
+ const autoFiles = existsSync(autosDirFull)
52
+ ? readdirSync(autosDirFull).filter((name) => name.endsWith(".auto.json")).sort()
53
+ : [];
54
+ const deployed = [];
55
+ for (const fileName of autoFiles) {
56
+ const relPath = slash(join(link.autosDir, fileName));
57
+ const result = loadAutoAndPlan(join(autosDirFull, fileName), project);
58
+ if (!result.ok || hasErrors(result.loaded.findings)) {
59
+ errors += 1;
60
+ actions.push({ kind: "skip", path: relPath, reason: "has validation errors; run zenith validate" });
61
+ continue;
62
+ }
63
+ deployed.push({
64
+ name: result.loaded.auto.name,
65
+ title: result.loaded.auto.title ?? result.loaded.auto.name,
66
+ relPath,
67
+ });
68
+ actions.push({ kind: "copy", from: relPath, path: slash(join(link.deploy.dir, fileName)) });
69
+ }
70
+ if (link.waypoints !== undefined) {
71
+ actions.push({
72
+ kind: "copy",
73
+ from: link.waypoints,
74
+ path: slash(join(link.deploy.dir, basename(link.waypoints))),
75
+ });
76
+ }
77
+ actions.push({ kind: "copy", from: link.robot, path: slash(join(link.deploy.dir, basename(link.robot))) });
78
+ actions.push({ kind: "copy", from: link.field, path: slash(join(link.deploy.dir, basename(link.field))) });
79
+ if (link.codegen !== undefined && commandLibrary !== undefined) {
80
+ const codegen = link.codegen;
81
+ const robotClass = link.deploy.robotClass;
82
+ if (robotClass === undefined) {
83
+ throw new ProjectError('zenith.json has "codegen" but no "deploy.robotClass". Every OpMode zenith deploy writes constructs your ' +
84
+ 'robot: set "deploy.robotClass" to your ZenithRobot class, fully qualified ' +
85
+ '(for example "org.firstinspires.ftc.teamcode.zenith.MyRobot"). See robot/README.md.');
86
+ }
87
+ const preselectTeleOp = link.deploy.preselectTeleOp;
88
+ const packagePath = codegen.package.split(".").join("/");
89
+ const generatedDir = join(codegen.dir, packagePath, "generated");
90
+ // codegen.dir itself was already confined to the project root by loadProject; packagePath comes
91
+ // from codegen.package (a dotted Java package name) and is re-confined here too, so a package
92
+ // name someone wrote as "..\\..\\evil" can't walk the generated-stub directory back out.
93
+ const generatedDirFull = confinePath(project.root, generatedDir);
94
+ const expected = new Map(); // file name -> content
95
+ for (const auto of deployed) {
96
+ const fileName = `${pascalCase(auto.name)}Auto.java`;
97
+ const className = fileName.replace(/\.java$/, "");
98
+ expected.set(fileName, autoStub({
99
+ packageName: codegen.package,
100
+ className,
101
+ autoName: auto.name,
102
+ title: auto.title,
103
+ relSource: auto.relPath,
104
+ robotClass,
105
+ ...(preselectTeleOp === undefined ? {} : { preselectTeleOp }),
106
+ commandLibrary,
107
+ }));
108
+ }
109
+ const existing = existsSync(generatedDirFull)
110
+ ? readdirSync(generatedDirFull).filter((name) => name.endsWith(".java"))
111
+ : [];
112
+ for (const [fileName, content] of expected) {
113
+ const relStub = slash(join(generatedDir, fileName));
114
+ const fullStub = join(generatedDirFull, fileName);
115
+ const current = existsSync(fullStub) ? readFileSync(fullStub, "utf8") : null;
116
+ actions.push({ kind: current === content ? "keep" : "write", path: relStub, content });
117
+ }
118
+ for (const fileName of existing) {
119
+ if (expected.has(fileName))
120
+ continue;
121
+ actions.push({ kind: "remove", path: slash(join(generatedDir, fileName)) });
122
+ }
123
+ }
124
+ return { commandLibrary, actions, errors };
125
+ }
126
+ /** Performs the actions `planDeploy` worked out. `keep` and `skip` need nothing done. */
127
+ export function applyDeploy(project, plan) {
128
+ for (const action of plan.actions) {
129
+ // The last line of defense before any write or delete: every action.path was built from
130
+ // already-confined directories, but confining it again here, right at the filesystem call,
131
+ // means this function alone is enough to guarantee deploy never touches anything outside the
132
+ // project root (finding 13) even if a future action ever computed a path some other way.
133
+ const full = confinePath(project.root, action.path);
134
+ if (action.kind === "copy" && action.from !== undefined) {
135
+ mkdirSync(dirname(full), { recursive: true });
136
+ copyFileSync(confinePath(project.root, action.from), full);
137
+ }
138
+ else if (action.kind === "write" && action.content !== undefined) {
139
+ mkdirSync(dirname(full), { recursive: true });
140
+ writeFileSync(full, action.content, "utf8");
141
+ }
142
+ else if (action.kind === "remove") {
143
+ rmSync(full, { force: true });
144
+ }
145
+ }
146
+ }
147
+ /**
148
+ * `zenith deploy`: copies every valid auto plus `waypoints.json`, `robot.json` and the field file to
149
+ * `zenith.json.deploy.dir`, and writes or refreshes one `@Autonomous` stub per auto under
150
+ * `codegen.dir/<package>/generated/` (site/docs/robot-runtime.md), removing
151
+ * stubs for autos that no longer exist. The stubs are written only when `zenith.json` has a `codegen`
152
+ * section, and only then is `deploy.commandLibrary` required. `--dry-run` only lists what it would do.
153
+ */
154
+ export function runDeploy(options) {
155
+ const cwd = options.cwd ?? process.cwd();
156
+ const project = loadProject(cwd, options.project);
157
+ const plan = planDeploy(project);
158
+ if (options.dryRun !== true)
159
+ applyDeploy(project, plan);
160
+ if (options.json === true) {
161
+ process.stdout.write(`${JSON.stringify({
162
+ project: slash(project.root),
163
+ dryRun: options.dryRun === true,
164
+ commandLibrary: plan.commandLibrary ?? null,
165
+ actions: plan.actions.map(({ content: _content, ...rest }) => rest),
166
+ errors: plan.errors,
167
+ }, null, 2)}\n`);
168
+ }
169
+ else {
170
+ process.stdout.write(plan.commandLibrary === undefined
171
+ ? 'command library: none named, and none needed: zenith.json has no "codegen" section, so no Java is written\n'
172
+ : `command library: ${LIBRARY_LABEL[plan.commandLibrary]} (${RUNTIME_PACKAGE[plan.commandLibrary]})\n`);
173
+ for (const action of plan.actions) {
174
+ const suffix = action.kind === "skip" ? ` (${action.reason ?? ""})` : "";
175
+ process.stdout.write(`${action.kind}: ${action.path}${suffix}\n`);
176
+ }
177
+ process.stdout.write(`${String(plan.errors)} auto(s) skipped for validation errors\n`);
178
+ }
179
+ return plan.errors === 0 ? 0 : 1;
180
+ }
181
+ //# sourceMappingURL=deploy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export interface DiffOptions {
2
+ cwd?: string;
3
+ json?: boolean;
4
+ }
5
+ /**
6
+ * `zenith diff <a> <b> [--json]`: the structural diff of site/docs/github.md, for review and for an
7
+ * agent comparing its own iterations. Needs only the two `Auto` documents, so it does not touch
8
+ * `zenith.json` at all beyond finding it for a nicer relative path.
9
+ */
10
+ export declare function runDiff(aArg: string, bArg: string, options: DiffOptions): number;
11
+ //# sourceMappingURL=diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/commands/diff.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAoBD;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,MAAM,CAiChF"}
@@ -0,0 +1,68 @@
1
+ import { isAbsolute, relative, resolve as resolvePath } from "node:path";
2
+ import { diff as coreDiff, diffToMarkdown, loadAuto } from "@horizon36596/zenith-core";
3
+ import { SchemaError } from "@horizon36596/zenith-schema";
4
+ import { CORE_NOT_LANDED_EXIT_CODE, tryCore } from "../coreGate.js";
5
+ import { findProjectRoot, readJsonFile } from "../project.js";
6
+ const slash = (path) => path.split("\\").join("/");
7
+ function loadOne(cwd, arg) {
8
+ const full = isAbsolute(arg) ? arg : resolvePath(cwd, arg);
9
+ let json;
10
+ try {
11
+ json = readJsonFile(full);
12
+ }
13
+ catch (error) {
14
+ return { ok: false, message: error instanceof Error ? error.message : String(error) };
15
+ }
16
+ try {
17
+ return { ok: true, auto: loadAuto(json) };
18
+ }
19
+ catch (error) {
20
+ if (error instanceof SchemaError)
21
+ return { ok: false, message: error.message };
22
+ return { ok: false, message: error instanceof Error ? error.message : String(error) };
23
+ }
24
+ }
25
+ /**
26
+ * `zenith diff <a> <b> [--json]`: the structural diff of site/docs/github.md, for review and for an
27
+ * agent comparing its own iterations. Needs only the two `Auto` documents, so it does not touch
28
+ * `zenith.json` at all beyond finding it for a nicer relative path.
29
+ */
30
+ export function runDiff(aArg, bArg, options) {
31
+ const cwd = options.cwd ?? process.cwd();
32
+ const a = loadOne(cwd, aArg);
33
+ const b = loadOne(cwd, bArg);
34
+ if (!a.ok || !b.ok) {
35
+ const problems = [];
36
+ if (!a.ok)
37
+ problems.push(`${aArg}: ${a.message}`);
38
+ if (!b.ok)
39
+ problems.push(`${bArg}: ${b.message}`);
40
+ const message = `cannot diff: ${problems.join("; ")}`;
41
+ if (options.json === true)
42
+ process.stdout.write(`${JSON.stringify({ error: message }, null, 2)}\n`);
43
+ else
44
+ process.stderr.write(`${message}\n`);
45
+ return 2;
46
+ }
47
+ const outcome = tryCore(() => coreDiff(a.auto, b.auto));
48
+ if (!outcome.ok) {
49
+ if (options.json === true)
50
+ process.stdout.write(`${JSON.stringify({ error: outcome.message }, null, 2)}\n`);
51
+ else
52
+ process.stderr.write(`${outcome.message}\n`);
53
+ return CORE_NOT_LANDED_EXIT_CODE;
54
+ }
55
+ const root = findProjectRoot(cwd);
56
+ const label = (arg) => {
57
+ const full = isAbsolute(arg) ? arg : resolvePath(cwd, arg);
58
+ return slash(root === null ? relative(cwd, full) : relative(root, full));
59
+ };
60
+ if (options.json === true) {
61
+ process.stdout.write(`${JSON.stringify({ a: label(aArg), b: label(bArg), diff: outcome.value }, null, 2)}\n`);
62
+ }
63
+ else {
64
+ process.stdout.write(`# ${label(aArg)} vs ${label(bArg)}\n\n${diffToMarkdown(outcome.value)}\n`);
65
+ }
66
+ return 0;
67
+ }
68
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/commands/diff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export interface EstimateOptions {
2
+ cwd?: string;
3
+ project?: string;
4
+ json?: boolean;
5
+ explain?: boolean;
6
+ }
7
+ /** `zenith estimate <auto> [--json] [--explain]`: the per-step time table of `03` section 3. */
8
+ export declare function runEstimate(autoArg: string, options: EstimateOptions): number;
9
+ //# sourceMappingURL=estimate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"estimate.d.ts","sourceRoot":"","sources":["../../src/commands/estimate.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAyBD,gGAAgG;AAChG,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,MAAM,CAsD7E"}