craftar 0.33.0 → 0.34.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.
@@ -226,8 +226,8 @@ export async function listFiles(dir, rel = "") {
226
226
  return out.sort();
227
227
  }
228
228
  /* ---- the scratch copy a Forge proof runs on, and the link check its writes share (spec 30 `drift promote`, spec 29 `forge promote`) ---- */
229
- const SYMLINK_REFUSAL = (rel) => `${rel} is a symbolic link in the Forge — promote does not write through a link; replace it with the file and commit`;
230
- const SYMLINK_DIR_REFUSAL = (rel) => `${rel} is a symbolic link in the Forge — promote does not read a linked recipes, ingredients or profiles directory; replace it with the directory and commit`;
229
+ const SYMLINK_REFUSAL = (rel, command) => `${rel} is a symbolic link in the Forge — ${command} does not write through a link; replace it with the file and commit`;
230
+ const SYMLINK_DIR_REFUSAL = (rel, command) => `${rel} is a symbolic link in the Forge — ${command} does not read a linked recipes, ingredients or profiles directory; replace it with the directory and commit`;
231
231
  const SYMLINK_OUT_OR_DANGLING = (rel) => `${rel} is a symbolic link out of the Forge, or to nothing — promote cannot copy the Forge to prove its edit; fix or remove it`;
232
232
  const NON_REGULAR_FILE_REFUSAL = (rel) => `${rel} is not a regular file — promote cannot copy the Forge to prove its edit; remove it`;
233
233
  /** The root directories loadForge reads; a link there causes the scratch to differ from the real Forge. */
@@ -273,7 +273,7 @@ export async function copyForgeForProof(forgeDir, scratchDir) {
273
273
  // A root directory link (ingredients, recipes, profiles) is refused: loadForge follows it
274
274
  // but the scratch would skip it, so the scratch would not load the same as the real Forge.
275
275
  if (rel === "" && ROOT_DIRS.has(ent.name)) {
276
- throw new Error(SYMLINK_DIR_REFUSAL(ent.name));
276
+ throw new Error(SYMLINK_DIR_REFUSAL(ent.name, "promote"));
277
277
  }
278
278
  // Other directory links are skipped entirely — loadForge doesn't traverse them
279
279
  continue;
@@ -316,7 +316,7 @@ export async function copyForgeForProof(forgeDir, scratchDir) {
316
316
  * Refuse a write through a symbolic link: every path, and every ancestor between it and `forgeDir`, that exists must
317
317
  * not be one. A path that does not exist yet is fine — it will be created.
318
318
  */
319
- export async function assertNoLinkOnPath(forgeDir, paths) {
319
+ export async function assertNoLinkOnPath(forgeDir, paths, command = "promote") {
320
320
  const checked = new Set();
321
321
  for (const abs of paths) {
322
322
  // The path and every ancestor up to but not including forgeDir
@@ -331,9 +331,9 @@ export async function assertNoLinkOnPath(forgeDir, paths) {
331
331
  const rel = path.relative(forgeDir, current).split(path.sep).join("/");
332
332
  // The directory-specific message for a root directory (ingredients, recipes, profiles)
333
333
  if (ROOT_DIRS.has(rel)) {
334
- throw new Error(SYMLINK_DIR_REFUSAL(rel));
334
+ throw new Error(SYMLINK_DIR_REFUSAL(rel, command));
335
335
  }
336
- throw new Error(SYMLINK_REFUSAL(rel));
336
+ throw new Error(SYMLINK_REFUSAL(rel, command));
337
337
  }
338
338
  }
339
339
  catch (e) {
@@ -1 +1 @@
1
- {"version":3,"file":"forge.js","sourceRoot":"","sources":["../../src/core/forge.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"forge.js","sourceRoot":"","sources":["../../src/core/forge.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,11 @@
1
1
  import { existsSync } from "node:fs";
2
- import { TARGETS } from "../schema/index.js";
2
+ import { ProfileSchema, TARGETS } from "../schema/index.js";
3
3
  import { planClone } from "./clone.js";
4
4
  import { countStates } from "./impact.js";
5
5
  import { resolveHome } from "./home-lock.js";
6
6
  import { checkInitFlags, checkLocalKeys, forgeSource, initLine } from "./init.js";
7
+ import { ownedBy, ownedRecipeRefusal, profileName, withProfile } from "./new-profile.js";
8
+ import { newProfileGate } from "./new-profile-gate.js";
7
9
  import { planRecipeEdit, slotHeld } from "./recipe-edit.js";
8
10
  import { readRegistry } from "./registry.js";
9
11
  import { classifyForge, credentialFault, CREDENTIAL_HIDDEN, refHoldsCredentials } from "./remote.js";
@@ -140,7 +142,17 @@ export async function askClone(io, init, opts) {
140
142
  * is refused (spec 29 §4.1) says so before the question, which then offers no sync.
141
143
  */
142
144
  export async function confirmInit(init, root, io, opts) {
143
- io.say(`craftar init — about to write craftar.yaml in ${root}`);
145
+ // Spec 38 §4.3: blockNote first when there is one
146
+ if (init.newProfile?.blockNote) {
147
+ io.say(` note ${init.newProfile.blockNote}`);
148
+ }
149
+ // Spec 38 §4.3: the first line changes with newProfile
150
+ if (init.newProfile) {
151
+ io.say(`craftar init — about to create profile ${init.ws.config.profile} in ${init.ws.forge.root} and write craftar.yaml in ${root}`);
152
+ }
153
+ else {
154
+ io.say(`craftar init — about to write craftar.yaml in ${root}`);
155
+ }
144
156
  io.say(` ${initLine(init)}`);
145
157
  const unset = unsetDeclared(init.plan);
146
158
  const counts = countStates(init.statuses);
@@ -158,10 +170,20 @@ export async function confirmInit(init, root, io, opts) {
158
170
  if (unset.length > 0 && opts.cloneRefused) {
159
171
  io.say(NOT_CLONED_REFUSED);
160
172
  }
161
- // Build the question
173
+ // Build the question: spec 38 §4.3 — with newProfile, the question names both writes
162
174
  let question;
163
175
  const clone = opts.clone ?? 0;
164
- if (unset.length > 0) {
176
+ const profileName = init.newProfile ? init.ws.config.profile : null;
177
+ if (init.newProfile) {
178
+ // New profile: different question forms
179
+ if (unset.length > 0 || !opts.sync) {
180
+ question = `Create profiles/${profileName}/profile.yaml (not committed) and write craftar.yaml [yes]: `;
181
+ }
182
+ else {
183
+ question = `Create profiles/${profileName}/profile.yaml (not committed), write craftar.yaml and sync [yes]: `;
184
+ }
185
+ }
186
+ else if (unset.length > 0) {
165
187
  // Sync refused → offer only craftar.yaml
166
188
  question = "Write craftar.yaml [yes]: ";
167
189
  }
@@ -324,6 +346,11 @@ export async function askInit(root, given, local, io, opts) {
324
346
  continue forgeLoop;
325
347
  }
326
348
  }
349
+ // P4 check: with --new-profile typed and Forge asked, a URL answer is refused — say P4 and ask again
350
+ if (given.newProfile !== undefined && classifyForge(forgeValue) === "url") {
351
+ io.say("a new profile is written into a Forge directory — clone the Forge, pass that directory as --forge, then commit and push the profile");
352
+ continue forgeLoop;
353
+ }
327
354
  forgeDefault = forgeValue;
328
355
  }
329
356
  answeredForge = forgeValue;
@@ -393,19 +420,45 @@ export async function askInit(root, given, local, io, opts) {
393
420
  throw e;
394
421
  }
395
422
  }
423
+ // P5/P6 check: with --new-profile typed and Forge asked, check if the Forge can take a new profile
424
+ if (given.newProfile !== undefined && forgeWasAsked) {
425
+ try {
426
+ await newProfileGate(loaded.forge, home);
427
+ }
428
+ catch (e) {
429
+ io.say(e.message);
430
+ forgeDefault = forgeValue;
431
+ refDefault = answeredRef ?? refDefault;
432
+ continue forgeLoop;
433
+ }
434
+ }
435
+ // P5/P6 check: with no profile given and no profiles in the Forge, we'll be forced to create a new profile
436
+ // If the Forge was asked and it can't take a new profile, say the error and ask again
437
+ if (given.profile === undefined && given.newProfile === undefined && loaded.forge.profiles.size === 0 && forgeWasAsked) {
438
+ if (classifyForge(forgeValue) !== "url") {
439
+ try {
440
+ await newProfileGate(loaded.forge, home);
441
+ }
442
+ catch (e) {
443
+ io.say(e.message);
444
+ forgeDefault = forgeValue;
445
+ refDefault = answeredRef ?? refDefault;
446
+ continue forgeLoop;
447
+ }
448
+ }
449
+ }
396
450
  break forgeLoop;
397
451
  }
398
452
  const forge = loaded.forge;
399
- if (forge.profiles.size === 0 && given.profile === undefined) {
400
- throw new Error("the Forge has no profile — add one under profiles/, then re-run init");
401
- }
402
- if (given.profile !== undefined) {
403
- if (!forge.profiles.has(given.profile)) {
404
- throw new Error(profileNotFoundMessage(given.profile, [...forge.profiles.keys()]));
405
- }
406
- answeredProfile = given.profile;
407
- }
408
- else {
453
+ // Track whether we're in the new-profile flow
454
+ let isNewProfile = false;
455
+ let newProfileName;
456
+ let newProfileLike;
457
+ let profileListShown = false;
458
+ // Helper to show the profile list
459
+ const showProfileList = () => {
460
+ if (profileListShown)
461
+ return;
409
462
  const profiles = [...forge.profiles.values()].sort((a, b) => a.name.localeCompare(b.name));
410
463
  io.say(`Profiles in ${answeredForge}:`);
411
464
  const maxLen = Math.max(...profiles.map((p) => p.name.length));
@@ -419,6 +472,68 @@ export async function askInit(root, given, local, io, opts) {
419
472
  io.say(` ${i + 1}) ${p.name}`);
420
473
  }
421
474
  }
475
+ profileListShown = true;
476
+ };
477
+ // Check if the new profile entry should be shown: Forge is a directory that passes P5/P6
478
+ let canOfferNewProfile = false;
479
+ let newProfileGateError = null;
480
+ if (classifyForge(answeredForge) !== "url") {
481
+ try {
482
+ await newProfileGate(forge, home);
483
+ canOfferNewProfile = true;
484
+ }
485
+ catch (e) {
486
+ newProfileGateError = e.message;
487
+ }
488
+ }
489
+ // Handle given.newProfile: validate with P3 and P7/P8 (typed value is not re-asked)
490
+ if (given.newProfile !== undefined) {
491
+ profileName(given.newProfile); // P3: throws on failure
492
+ // P9 up front: a typed --like the Forge does not have is refused before any question
493
+ if (given.like !== undefined && !forge.profiles.has(given.like)) {
494
+ throw new Error("--like: " + profileNotFoundMessage(given.like, [...forge.profiles.keys()]));
495
+ }
496
+ await newProfileGate(forge, home, given.newProfile); // P7/P8: throws on failure
497
+ isNewProfile = true;
498
+ newProfileName = given.newProfile;
499
+ newProfileLike = given.like;
500
+ answeredProfile = given.newProfile;
501
+ }
502
+ else if (given.profile !== undefined) {
503
+ if (!forge.profiles.has(given.profile)) {
504
+ throw new Error(profileNotFoundMessage(given.profile, [...forge.profiles.keys()]));
505
+ }
506
+ answeredProfile = given.profile;
507
+ }
508
+ else if (forge.profiles.size === 0) {
509
+ // Spec 38 §4.3: A Forge directory with no profile goes straight to the new-profile questions
510
+ // (A URL Forge with no profile keeps today's error)
511
+ if (classifyForge(answeredForge) === "url") {
512
+ throw new Error("the Forge has no profile — add one under profiles/, then re-run init");
513
+ }
514
+ // For directory Forge with no profile: check if it can take a new profile
515
+ if (!canOfferNewProfile) {
516
+ throw new Error(newProfileGateError);
517
+ }
518
+ io.say("the Forge has no profile yet — creating the first one");
519
+ isNewProfile = true;
520
+ }
521
+ else {
522
+ // Show the profile list with the new profile entry if applicable
523
+ const profiles = [...forge.profiles.values()].sort((a, b) => a.name.localeCompare(b.name));
524
+ showProfileList();
525
+ // Show the 0) a new profile entry ONLY when the Forge can take a new profile
526
+ // Per spec 38 §4.3: show lines explaining why the entry isn't available
527
+ if (canOfferNewProfile) {
528
+ io.say(" 0) a new profile");
529
+ }
530
+ else if (classifyForge(answeredForge) === "url") {
531
+ io.say("a new profile needs a Forge directory");
532
+ }
533
+ else if (newProfileGateError) {
534
+ // Forge directory that fails P5/P6: show the error as the line under the list
535
+ io.say(newProfileGateError);
536
+ }
422
537
  const defProfile = profiles.length === 1 ? profiles[0].name : null;
423
538
  const profileQ = defProfile !== null ? `Profile [${defProfile}]: ` : "Profile: ";
424
539
  profileLoop: for (;;) {
@@ -434,14 +549,342 @@ export async function askInit(root, given, local, io, opts) {
434
549
  answeredProfile = defProfile;
435
550
  break profileLoop;
436
551
  }
552
+ // pickItem: names first, then (only when the entry is shown) "0" for new profile, then numbers
437
553
  const picked = pickItem(profiles.map((p) => p.name), trimmed);
438
554
  if (picked !== null) {
439
555
  answeredProfile = picked;
440
556
  break profileLoop;
441
557
  }
558
+ // Check for "0" to start new-profile questions (only when the entry is shown)
559
+ if (canOfferNewProfile && trimmed === "0") {
560
+ isNewProfile = true;
561
+ break profileLoop;
562
+ }
442
563
  io.say(profileNotFoundMessage(trimmed, [...forge.profiles.keys()]));
443
564
  }
444
565
  }
566
+ // New-profile questions (§4.3)
567
+ if (isNewProfile) {
568
+ // Name question (skipped when given.newProfile was typed)
569
+ if (newProfileName === undefined) {
570
+ nameLoop: for (;;) {
571
+ const answer = await io.ask("New profile's name: ");
572
+ if (answer === null)
573
+ return { kind: "cancelled" };
574
+ const trimmed = answer.trim();
575
+ if (trimmed === "") {
576
+ io.say('a name is needed — lowercase letters and digits, in groups joined by one "-"');
577
+ continue nameLoop;
578
+ }
579
+ try {
580
+ profileName(trimmed); // P3
581
+ await newProfileGate(forge, home, trimmed); // P7, P8
582
+ newProfileName = trimmed;
583
+ break nameLoop;
584
+ }
585
+ catch (e) {
586
+ io.say(e.message);
587
+ continue nameLoop;
588
+ }
589
+ }
590
+ }
591
+ answeredProfile = newProfileName;
592
+ // Template question: "Start from an existing profile [none]:" — only when the Forge has profiles
593
+ // and when given.like was not provided
594
+ if (newProfileLike === undefined && forge.profiles.size > 0) {
595
+ // Print the profile list if it wasn't printed yet (e.g. --new-profile was typed, --forge asked)
596
+ if (!profileListShown) {
597
+ showProfileList();
598
+ }
599
+ templateLoop: for (;;) {
600
+ const answer = await io.ask("Start from an existing profile [none]: ");
601
+ if (answer === null)
602
+ return { kind: "cancelled" };
603
+ const trimmed = answer.trim();
604
+ if (trimmed === "" || trimmed === "0") {
605
+ // Enter or 0 → none
606
+ break templateLoop;
607
+ }
608
+ const profiles = [...forge.profiles.values()].sort((a, b) => a.name.localeCompare(b.name));
609
+ const picked = pickItem(profiles.map((p) => p.name), trimmed);
610
+ if (picked !== null) {
611
+ newProfileLike = picked;
612
+ break templateLoop;
613
+ }
614
+ // Unknown → say "--like: " + profileNotFoundMessage
615
+ io.say("--like: " + profileNotFoundMessage(trimmed, [...forge.profiles.keys()]));
616
+ continue templateLoop;
617
+ }
618
+ }
619
+ // Recipes question for new profile
620
+ // With a template: show "Recipes of <name> (from <like>): <chain>" then Adjust flow
621
+ // Without a template: show recipes list and ask "Add [none]:" directly
622
+ let finalAddRecipes = [];
623
+ let finalRemoveRecipes = [];
624
+ let finalReplace = false;
625
+ // Typed flags answer their questions (spec 38 §4.2, §4.3)
626
+ const recipesFlagged = given.addRecipes.length > 0 || given.removeRecipes.length > 0;
627
+ if (recipesFlagged) {
628
+ // Use the flags directly, skip all recipe questions
629
+ finalAddRecipes = given.addRecipes;
630
+ finalRemoveRecipes = given.removeRecipes;
631
+ finalReplace = given.replace;
632
+ }
633
+ else if (local.keys.includes("recipes")) {
634
+ // local.keys includes recipes and no recipe flag typed: no recipes question; say the chain from the draft resolved with local recipes
635
+ const templateRecipes = newProfileLike ? forge.profiles.get(newProfileLike).recipes : [];
636
+ const draftProfile = ProfileSchema.parse({ name: newProfileName, recipes: templateRecipes, targets: [] });
637
+ const draftCopy = withProfile(forge, draftProfile);
638
+ const recipeConfig = { ...localConfig, profile: newProfileName };
639
+ const resolution = resolve(draftCopy, recipeConfig);
640
+ io.say(`Recipes: ${resolution.recipes.join(" → ")} (from craftar.local.yaml)`);
641
+ }
642
+ else {
643
+ // Track whether we should start with Remove (after a P10 error)
644
+ let startWithRemove = false;
645
+ recipeLoop: for (;;) {
646
+ // Compute the draft profile in a copy of the Forge for the recipes line
647
+ const template = newProfileLike ? forge.profiles.get(newProfileLike) : undefined;
648
+ const draftRecipes = template?.recipes ?? [];
649
+ if (template && !startWithRemove) {
650
+ // With a template: show the chain resolved from the draft profile
651
+ const draft = ProfileSchema.parse({ name: newProfileName, recipes: draftRecipes, targets: template.targets });
652
+ const copy = withProfile(forge, draft);
653
+ // Use mergeWorkspaceConfig to get a valid config with overrides
654
+ const config = mergeWorkspaceConfig({ forge: forgeSource(root, answeredForge), profile: newProfileName }, null).config;
655
+ const resolution = resolve(copy, config);
656
+ io.say(`Recipes of ${newProfileName} (from ${newProfileLike}): ${resolution.recipes.join(" → ")}`);
657
+ // Adjust the recipes [no]:
658
+ const adjustAns = await io.ask("Adjust the recipes [no]: ");
659
+ if (adjustAns === null)
660
+ return { kind: "cancelled" };
661
+ const yn = yesNo(adjustAns);
662
+ if (adjustAns.trim() !== "" && yn === null) {
663
+ io.say("answer yes or no");
664
+ continue recipeLoop;
665
+ }
666
+ if (yn !== true) {
667
+ // No adjustment: check P10 on the template's recipes before accepting, using ownedBy
668
+ const templateRecipes = template.recipes;
669
+ for (const r of templateRecipes) {
670
+ const owner = ownedBy(forge, r);
671
+ if (owner !== null) {
672
+ io.say(ownedRecipeRefusal(r, owner));
673
+ startWithRemove = true;
674
+ continue recipeLoop;
675
+ }
676
+ }
677
+ // Success: use template's recipes as-is
678
+ break recipeLoop;
679
+ }
680
+ }
681
+ // Show the Forge's recipes list
682
+ io.say(`Recipes in ${answeredForge}:`);
683
+ const allRecipes = [...forge.recipes.values()].sort((a, b) => a.name.localeCompare(b.name));
684
+ for (let i = 0; i < allRecipes.length; i++) {
685
+ const r = allRecipes[i];
686
+ const parts = [` ${i + 1}) ${r.name}`];
687
+ if (draftRecipes.includes(r.name))
688
+ parts.push("· in use");
689
+ if (r.slot)
690
+ parts.push(`· slot ${r.slot}`);
691
+ if (r.description)
692
+ parts.push(`· ${r.description}`);
693
+ io.say(parts.join(" "));
694
+ }
695
+ const names = allRecipes.map((r) => r.name);
696
+ const parseRecipeAnswer = (answer) => answer.split(",").map((s) => s.trim()).filter((s) => s !== "").map((s) => pickItem(names, s) ?? s);
697
+ // Remove question (only with a template, or after P10 error)
698
+ let removeNames = [];
699
+ if (template || startWithRemove) {
700
+ const removeAns = await io.ask("Remove [none]: ");
701
+ if (removeAns === null)
702
+ return { kind: "cancelled" };
703
+ removeNames = parseRecipeAnswer(removeAns);
704
+ }
705
+ // Add question
706
+ const addAns = await io.ask("Add [none]: ");
707
+ if (addAns === null)
708
+ return { kind: "cancelled" };
709
+ let addNames = parseRecipeAnswer(addAns);
710
+ // Reset startWithRemove for the next iteration
711
+ startWithRemove = false;
712
+ if (removeNames.length === 0 && addNames.length === 0) {
713
+ // No changes entered: check P10 on the final list (same as template's recipes)
714
+ if (template) {
715
+ for (const r of template.recipes) {
716
+ const owner = ownedBy(forge, r);
717
+ if (owner !== null) {
718
+ io.say(ownedRecipeRefusal(r, owner));
719
+ startWithRemove = true;
720
+ continue recipeLoop;
721
+ }
722
+ }
723
+ }
724
+ // P10 passed or no template
725
+ break recipeLoop;
726
+ }
727
+ // N6 check: a name both added and removed — say and re-ask
728
+ const both = addNames.find((n) => removeNames.includes(n));
729
+ if (both !== undefined) {
730
+ try {
731
+ checkInitFlags({ addRecipes: addNames, removeRecipes: removeNames });
732
+ }
733
+ catch (e) {
734
+ io.say(e.message);
735
+ continue recipeLoop;
736
+ }
737
+ }
738
+ // Compute the recipe edit for notes and P10 check (mirroring existing flow)
739
+ // We do removes first, then adds — as init.ts and the existing flow do
740
+ const editConfig = mergeWorkspaceConfig({ forge: forgeSource(root, answeredForge), profile: newProfileName }, null).config;
741
+ let tempConfig = { ...editConfig, recipes: { add: [], remove: [] } };
742
+ // Simulate the edits on the template to get notes
743
+ const templateRecipes = newProfileLike ? forge.profiles.get(newProfileLike).recipes : [];
744
+ const draftProfile = ProfileSchema.parse({ name: newProfileName, recipes: templateRecipes, targets: [] });
745
+ const draftCopy = withProfile(forge, draftProfile);
746
+ // The remove edit and add loop inside one outer try: any refusal → say the message and continue recipeLoop
747
+ try {
748
+ // Process removes, say notes
749
+ if (removeNames.length > 0) {
750
+ const removeEdit = planRecipeEdit(draftCopy, tempConfig, "remove", removeNames);
751
+ tempConfig = { ...tempConfig, recipes: removeEdit.recipes };
752
+ if (removeEdit.reasons.length > 0) {
753
+ io.say(` note ${removeEdit.reasons.join(", ")}`);
754
+ }
755
+ }
756
+ // Process adds, say notes, handle slot held
757
+ let doReplace = false;
758
+ addSlotLoop: for (;;) {
759
+ try {
760
+ const addEdit = planRecipeEdit(draftCopy, tempConfig, "add", addNames, { replace: doReplace });
761
+ tempConfig = { ...tempConfig, recipes: addEdit.recipes };
762
+ if (addEdit.reasons.length > 0) {
763
+ io.say(` note ${addEdit.reasons.join(", ")}`);
764
+ }
765
+ break addSlotLoop;
766
+ }
767
+ catch (e) {
768
+ const held = slotHeld(e);
769
+ if (held !== null && !doReplace) {
770
+ const replaceQ = `${held.recipe} takes the slot "${held.slot}" that ${held.holder} holds — replace ${held.holder} [no]: `;
771
+ let replaceYn;
772
+ for (;;) {
773
+ const replaceAns = await io.ask(replaceQ);
774
+ if (replaceAns === null)
775
+ return { kind: "cancelled" };
776
+ replaceYn = replaceAns.trim() === "" ? false : yesNo(replaceAns);
777
+ if (replaceYn !== null)
778
+ break;
779
+ io.say("answer yes or no");
780
+ }
781
+ if (replaceYn) {
782
+ doReplace = true;
783
+ continue addSlotLoop;
784
+ }
785
+ // User said no to replace, re-ask recipes
786
+ continue recipeLoop;
787
+ }
788
+ // Other errors (unknown recipe, etc.): re-throw to outer try
789
+ throw e;
790
+ }
791
+ }
792
+ // Compute the final list: template's recipes minus removes, plus adds
793
+ const finalList = [
794
+ ...templateRecipes.filter((r) => !tempConfig.recipes.remove.includes(r)),
795
+ ...tempConfig.recipes.add,
796
+ ];
797
+ // P10 check on the final list
798
+ for (const r of finalList) {
799
+ const owner = ownedBy(forge, r);
800
+ if (owner !== null) {
801
+ io.say(ownedRecipeRefusal(r, owner));
802
+ startWithRemove = true;
803
+ continue recipeLoop;
804
+ }
805
+ }
806
+ // Success
807
+ finalAddRecipes = addNames;
808
+ finalRemoveRecipes = removeNames;
809
+ finalReplace = doReplace;
810
+ break recipeLoop;
811
+ }
812
+ catch (e) {
813
+ io.say(e.message);
814
+ continue recipeLoop;
815
+ }
816
+ }
817
+ }
818
+ answeredAddRecipes = finalAddRecipes;
819
+ answeredRemoveRecipes = finalRemoveRecipes;
820
+ answeredReplace = finalReplace;
821
+ // Targets question for new profile
822
+ // Typed flags answer their questions (spec 38 §4.2, §4.3)
823
+ if (given.targets !== undefined) {
824
+ answeredTargets = given.targets;
825
+ }
826
+ else if (local.keys.includes("targets")) {
827
+ // local.keys includes targets and no --targets typed: no targets question; say the local value
828
+ const localTargets = localConfig?.targets ?? [];
829
+ io.say(`Targets: ${localTargets.join(", ")} (from craftar.local.yaml)`);
830
+ }
831
+ else {
832
+ // Default: [<template's targets>, from <like>] or [claude-code, default]
833
+ const template = newProfileLike ? forge.profiles.get(newProfileLike) : undefined;
834
+ const defaultTargets = template?.targets ?? ["claude-code"];
835
+ const fromText = template ? `from ${newProfileLike}` : "default";
836
+ const targetsQ = `Targets — ${TARGETS.join(", ")}, separated by commas [${defaultTargets.join(", ")}, ${fromText}]: `;
837
+ targetsLoop: for (;;) {
838
+ const answer = await io.ask(targetsQ);
839
+ if (answer === null)
840
+ return { kind: "cancelled" };
841
+ const trimmed = answer.trim();
842
+ if (trimmed === "")
843
+ break targetsLoop;
844
+ const parsed = trimmed.split(",").map((s) => s.trim());
845
+ try {
846
+ checkInitFlags({ targets: parsed });
847
+ }
848
+ catch (e) {
849
+ io.say(e.message);
850
+ continue targetsLoop;
851
+ }
852
+ answeredTargets = parsed;
853
+ break targetsLoop;
854
+ }
855
+ }
856
+ // Build the result for new profile
857
+ const input = {
858
+ forge: answeredForge,
859
+ profile: newProfileName,
860
+ loaded: loaded,
861
+ newProfile: newProfileLike ? { name: newProfileName, like: newProfileLike } : { name: newProfileName },
862
+ };
863
+ if (answeredRef !== undefined)
864
+ input.ref = answeredRef;
865
+ if (answeredTargets !== undefined)
866
+ input.targets = answeredTargets;
867
+ if (answeredAddRecipes.length > 0)
868
+ input.addRecipes = answeredAddRecipes;
869
+ if (answeredRemoveRecipes.length > 0)
870
+ input.removeRecipes = answeredRemoveRecipes;
871
+ if (answeredReplace)
872
+ input.replace = true;
873
+ if (given.clone === true)
874
+ input.clone = true;
875
+ // For new profile: answers has --profile name (for the again line), no recipe/target flags
876
+ const answers = {
877
+ forge: answeredForge,
878
+ profile: newProfileName,
879
+ addRecipes: [],
880
+ removeRecipes: [],
881
+ replace: false,
882
+ };
883
+ if (answeredRef !== undefined)
884
+ answers.ref = answeredRef;
885
+ return { kind: "answered", input, answers };
886
+ }
887
+ // Existing profile flow (unchanged)
445
888
  const profile = forge.profiles.get(answeredProfile);
446
889
  const recipesFlagged = given.addRecipes.length > 0 || given.removeRecipes.length > 0;
447
890
  if (recipesFlagged) {