@kybernesis/create 0.14.5 → 0.14.6

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/init.js CHANGED
@@ -74,7 +74,19 @@ export async function init(rawName, options = {}) {
74
74
  // refuses an id it cannot find in the AI Gateway catalog and then creates
75
75
  // nothing at all, and an exe-hosted agent takes its model from EXE_MODEL,
76
76
  // not from the gateway.
77
- run("npx", [`eve@${EVE_VERSION}`, "init", name], { allowFail: true });
77
+ // Two guards, both learned on a real Factory build (KYB-521):
78
+ // - AI_AGENT: eve's init hands off to `eve dev --onboard` when it sees no
79
+ // interactive terminal, and that is a server that waits for a person, so a
80
+ // headless `kyb init` never returned. eve skips the handoff and prints its
81
+ // summary when it believes a coding agent launched it; the marker is
82
+ // stripped from eve's own child spawns, so nothing else sees it.
83
+ // - a timeout, because `--yes` cannot reach a choice eve makes internally,
84
+ // and a scaffold that cannot finish must fail, not wait forever.
85
+ run("npx", [`eve@${EVE_VERSION}`, "init", name], {
86
+ allowFail: true,
87
+ env: { AI_AGENT: process.env.AI_AGENT?.trim() || "kybernesis-create" },
88
+ timeoutMs: 20 * 60_000,
89
+ });
78
90
  // The real test of that step, since its exit code cannot be trusted.
79
91
  if (!existsSync(join(dir, "package.json"))) {
80
92
  console.error(red(`\n eve did not create a project in ${dir}. Nothing else can run.`));
package/dist/upgrade.js CHANGED
@@ -424,13 +424,16 @@ function dependencyEntries(pkg) {
424
424
  function rewriteManifest(cwd, pkg, targets) {
425
425
  for (const target of targets) {
426
426
  const section = pkg[target.section];
427
- section[target.name] = `^${target.targetVersion}`;
427
+ // eve is pinned exactly: the pin IS the certification. A caret let a
428
+ // clean install resolve eve@0.49.1 against a certified 0.49.0 (blind
429
+ // latest, the one thing kyb upgrade exists to prevent).
430
+ section[target.name] = target.name === "eve" ? target.targetVersion : `^${target.targetVersion}`;
428
431
  }
429
432
  writeFileSync(join(cwd, "package.json"), `${JSON.stringify(pkg, null, 2)}\n`);
430
433
  }
431
434
  function recoveryGuidance(targets, bridgeUnit) {
432
435
  console.log(`\n${yellow("The dependency tree was not verified. Complete the clean install before using it:")}\n` +
433
- ` 1. Ensure every root @kybernesis/* and eve range in package.json is the resolved ^version.\n` +
436
+ ` 1. Ensure every root @kybernesis/* range in package.json is the resolved ^version, and eve is pinned exactly to ${EVE_VERSION}.\n` +
434
437
  ` 2. ${dim("rm -rf node_modules")}\n` +
435
438
  ` 3. ${dim("rm -f package-lock.json")}\n` +
436
439
  ` 4. ${dim("npm install")}\n` +
@@ -592,8 +595,15 @@ export async function upgrade(options = {}) {
592
595
  return;
593
596
  }
594
597
  }
595
- const installArgs = cleanInstall ? ["install"] : ["install", ...changed];
596
- const installed = commandResult("npm", installArgs, cwd);
598
+ // Outside a clean install, eve goes in with --save-exact for the same
599
+ // reason rewriteManifest pins it: npm would save a caret by default.
600
+ const eveChange = changed.find((spec) => spec.startsWith("eve@"));
601
+ const others = changed.filter((spec) => spec !== eveChange);
602
+ const installArgs = cleanInstall ? ["install"] : ["install", ...others];
603
+ let installed = cleanInstall || others.length > 0 ? commandResult("npm", installArgs, cwd) : { status: 0, stdout: "", stderr: "" };
604
+ if (installed.status === 0 && !cleanInstall && eveChange) {
605
+ installed = commandResult("npm", ["install", "--save-exact", eveChange], cwd);
606
+ }
597
607
  if (installed.status !== 0) {
598
608
  const output = `${installed.stdout}\n${installed.stderr}`;
599
609
  if (/ERESOLVE/i.test(output)) {
package/dist/util.d.ts CHANGED
@@ -10,6 +10,10 @@ export declare function run(command: string, args: string[], options?: {
10
10
  cwd?: string;
11
11
  allowFail?: boolean;
12
12
  quiet?: boolean;
13
+ /** Extra environment for this one child; the parent's is inherited underneath. */
14
+ env?: Record<string, string>;
15
+ /** Kill the child after this many milliseconds. A command that cannot finish is a failure, not a wait. */
16
+ timeoutMs?: number;
13
17
  }): boolean;
14
18
  export declare function capture(command: string, args: string[], cwd?: string, extraEnv?: Record<string, string>): string | null;
15
19
  export declare function ask(question: string, fallback: string): Promise<string>;
package/dist/util.js CHANGED
@@ -15,8 +15,12 @@ export function run(command, args, options) {
15
15
  const result = spawnSync(command, args, {
16
16
  cwd: options?.cwd,
17
17
  stdio: options?.quiet ? "pipe" : "inherit",
18
- env: process.env,
18
+ env: { ...process.env, ...options?.env },
19
+ timeout: options?.timeoutMs,
19
20
  });
21
+ if (result.error && result.error.code === "ETIMEDOUT") {
22
+ console.error(red(`Command did not finish within ${Math.round((options?.timeoutMs ?? 0) / 60_000)} min and was stopped: ${command} ${args.join(" ")}`));
23
+ }
20
24
  const ok = result.status === 0;
21
25
  if (!ok && !options?.allowFail) {
22
26
  console.error(red(`Command failed: ${command} ${args.join(" ")}`));
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@kybernesis/create",
3
- "version": "0.14.5",
4
- "description": "The Kybernesis agent scaffolder and FDE toolkit: one command to a governed, remembering, multiplayer, self-testing eve agent \u2014 plus doctor and upgrade.",
3
+ "version": "0.14.6",
4
+ "description": "The Kybernesis agent scaffolder and FDE toolkit: one command to a governed, remembering, multiplayer, self-testing eve agent — plus doctor and upgrade.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
7
7
  "homepage": "https://kybernesis.ai",