@theholocron/cli 5.0.0-alpha.167 → 5.0.0-alpha.168
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/dist/cli.mjs +78 -2
- package/dist/cli.mjs.map +1 -1
- package/package.json +3 -3
package/dist/cli.mjs
CHANGED
|
@@ -5217,6 +5217,50 @@ const STALE_LABELS = [
|
|
|
5217
5217
|
//#region src/templates/dco.yml
|
|
5218
5218
|
var dco_default = "allowRemediationCommits:\n individual: true\n";
|
|
5219
5219
|
//#endregion
|
|
5220
|
+
//#region src/commands/workflow-source-marker/workflow-source-marker.ts
|
|
5221
|
+
/** `# Source package: <path>` line at the head of a generated thin-caller workflow — see {@link resolvePkgRelPath}. */
|
|
5222
|
+
const SOURCE_PACKAGE_MARKER = /^# Source package: (.+)$/m;
|
|
5223
|
+
/** Strip control characters (including ANSI escapes) before a value reaches a printed error message. */
|
|
5224
|
+
function sanitizeForDisplay(value) {
|
|
5225
|
+
return value.replace(/[\x00-\x1f\x7f]/g, "");
|
|
5226
|
+
}
|
|
5227
|
+
/**
|
|
5228
|
+
* Repo-root-relative path of the PACKAGE a workflow-writing command run is
|
|
5229
|
+
* scoped to — the directory holding the discovered `holocron.config.*`
|
|
5230
|
+
* (`configFilepath`), not necessarily `--cwd` itself. `loadConfig()` walks
|
|
5231
|
+
* up to find the config from any subdirectory ("every command is usable
|
|
5232
|
+
* from any subdirectory of a repo, not only its exact root"), so a `--cwd`
|
|
5233
|
+
* one level too deep would otherwise stamp a different marker than a later
|
|
5234
|
+
* run from the package's own root and misfire the collision check this
|
|
5235
|
+
* feeds (holocron#1026).
|
|
5236
|
+
*
|
|
5237
|
+
* "." for a root invocation, "apps/sentinel" for a subpackage. Normalized
|
|
5238
|
+
* to forward slashes so the same package produces the same marker on
|
|
5239
|
+
* Windows and POSIX. Throws if the result contains a line break — a path
|
|
5240
|
+
* containing one could otherwise break out of the `# Source package: `
|
|
5241
|
+
* comment line and inject arbitrary workflow YAML when the generated
|
|
5242
|
+
* content is later written. Not reachable through this CLI's own flows
|
|
5243
|
+
* (no code path writes a config file whose directory name contains a line
|
|
5244
|
+
* break), but cheap to reject outright rather than trust the filesystem.
|
|
5245
|
+
*/
|
|
5246
|
+
function resolvePkgRelPath(gitRoot, configFilepath) {
|
|
5247
|
+
let root;
|
|
5248
|
+
try {
|
|
5249
|
+
root = realpathSync(gitRoot);
|
|
5250
|
+
} catch {
|
|
5251
|
+
root = gitRoot;
|
|
5252
|
+
}
|
|
5253
|
+
let configDir;
|
|
5254
|
+
try {
|
|
5255
|
+
configDir = realpathSync(dirname(configFilepath));
|
|
5256
|
+
} catch {
|
|
5257
|
+
configDir = dirname(configFilepath);
|
|
5258
|
+
}
|
|
5259
|
+
const pkgRelPath = (relative(root, configDir) || ".").split(sep).join("/");
|
|
5260
|
+
if (/[\r\n]/.test(pkgRelPath)) throw new Error(`refusing to use a package path containing a line break: ${JSON.stringify(pkgRelPath)}`);
|
|
5261
|
+
return pkgRelPath;
|
|
5262
|
+
}
|
|
5263
|
+
//#endregion
|
|
5220
5264
|
//#region src/commands/setup/agent-prompts-data.ts
|
|
5221
5265
|
/**
|
|
5222
5266
|
* Canonical AI engineering workflow role prompts.
|
|
@@ -6061,6 +6105,10 @@ async function runSetup(input) {
|
|
|
6061
6105
|
const steps = [];
|
|
6062
6106
|
const repo = config.repo;
|
|
6063
6107
|
const effectivePreset = repo?.protection;
|
|
6108
|
+
const setupPkgRelPath = resolvePkgRelPath(findRootSync(input.context.repoRoot, ".git", {
|
|
6109
|
+
fallback: "start",
|
|
6110
|
+
realpath: true
|
|
6111
|
+
}), input.loaded.filepath);
|
|
6064
6112
|
const hooksEnabled = input.hooks ?? (typeof config.hooks === "boolean" ? config.hooks : typeof config.hooks === "object" ? config.hooks.prePush !== false : effectivePreset === "strict");
|
|
6065
6113
|
print(style.header(`Holocron setup — ${config.name}${dryRun ? " (dry-run)" : ""}`));
|
|
6066
6114
|
print(style.dim(` config: ${input.loaded.filepath}`));
|
|
@@ -6140,7 +6188,7 @@ async function runSetup(input) {
|
|
|
6140
6188
|
if (content === void 0) continue;
|
|
6141
6189
|
const step = content.includes("workflows/preview.yml@main") ? `write workflow ${name} (with preview)` : `write workflow ${name}`;
|
|
6142
6190
|
steps.push(await runStep("source", step, dryRun, async () => {
|
|
6143
|
-
await source.writeWorkflowFile(filename, `${thinCallerHeader()}${content}`);
|
|
6191
|
+
await source.writeWorkflowFile(filename, `${thinCallerHeader()}# Source package: ${setupPkgRelPath}\n\n${content}`);
|
|
6144
6192
|
}));
|
|
6145
6193
|
print(formatStep(steps[steps.length - 1]));
|
|
6146
6194
|
}
|
|
@@ -7243,6 +7291,7 @@ async function runSync(input) {
|
|
|
7243
7291
|
} catch {
|
|
7244
7292
|
resolvedRepoRoot = input.context.repoRoot;
|
|
7245
7293
|
}
|
|
7294
|
+
const pkgRelPath = resolvePkgRelPath(gitRoot, input.loaded.filepath);
|
|
7246
7295
|
logger.info({
|
|
7247
7296
|
config: config.name,
|
|
7248
7297
|
steps: requestedSteps ?? "all",
|
|
@@ -7520,7 +7569,8 @@ async function runSync(input) {
|
|
|
7520
7569
|
if (content === void 0) continue;
|
|
7521
7570
|
const step = `sync workflow ${name}${content.includes("workflows/preview.yml@main") ? " (with preview)" : ""}`;
|
|
7522
7571
|
steps.push(await runSyncStep("local", step, dryRun, async () => {
|
|
7523
|
-
await
|
|
7572
|
+
await assertNoPackageCollision(gitRoot, filename, name, pkgRelPath);
|
|
7573
|
+
await writeWorkflowFile(gitRoot, filename, `${workflowHeader()}# Source package: ${pkgRelPath}\n\n${content}`);
|
|
7524
7574
|
}));
|
|
7525
7575
|
print(formatSyncStep(steps[steps.length - 1]));
|
|
7526
7576
|
}
|
|
@@ -7783,6 +7833,32 @@ async function writeWorkflowFile(repoRoot, filename, content) {
|
|
|
7783
7833
|
await writeFile(tmpPath, content, "utf8");
|
|
7784
7834
|
await rename(tmpPath, join(dir, filename));
|
|
7785
7835
|
}
|
|
7836
|
+
/**
|
|
7837
|
+
* Two different monorepo packages opting into the same generic task name
|
|
7838
|
+
* (e.g. both `apps/sentinel` and some future `apps/other` configuring
|
|
7839
|
+
* `delivery.previewDeploy`) would otherwise overwrite each other's
|
|
7840
|
+
* `.github/workflows/<task>.yml` on whichever package's `holocron repo sync`
|
|
7841
|
+
* ran last — only one package's behavior would ever actually run in CI,
|
|
7842
|
+
* with no signal that the other's was silently dropped (holocron#1026).
|
|
7843
|
+
*
|
|
7844
|
+
* A file with no marker at all predates this check (or was written before
|
|
7845
|
+
* #1026) and is never flagged — only a marker that's present AND disagrees
|
|
7846
|
+
* with the current run's own package is a real collision. Any read error
|
|
7847
|
+
* other than "file doesn't exist" propagates rather than being treated as
|
|
7848
|
+
* "nothing to collide with" — the file may genuinely be unreadable, not
|
|
7849
|
+
* missing.
|
|
7850
|
+
*/
|
|
7851
|
+
async function assertNoPackageCollision(repoRoot, filename, taskName, pkgRelPath) {
|
|
7852
|
+
let existing;
|
|
7853
|
+
try {
|
|
7854
|
+
existing = await readFile(join(repoRoot, ".github", "workflows", filename), "utf8");
|
|
7855
|
+
} catch (err) {
|
|
7856
|
+
if (err.code === "ENOENT") return;
|
|
7857
|
+
throw err;
|
|
7858
|
+
}
|
|
7859
|
+
const previousPkg = SOURCE_PACKAGE_MARKER.exec(existing)?.[1];
|
|
7860
|
+
if (previousPkg !== void 0 && previousPkg !== pkgRelPath) throw new Error(`task "${taskName}" would overwrite .github/workflows/${filename}, already generated for package "${sanitizeForDisplay(previousPkg)}" — the same task name can't be used by two different packages (holocron#1026). If "${sanitizeForDisplay(previousPkg)}" moved or was renamed to this path, delete .github/workflows/${filename} first and re-run sync; otherwise rename one or give it a different thin-caller filename.`);
|
|
7861
|
+
}
|
|
7786
7862
|
//#endregion
|
|
7787
7863
|
//#region src/observability/resolve-telemetry/resolve-telemetry.ts
|
|
7788
7864
|
/**
|