@snappedly-tools/shipyard 0.7.0-staging.36082887921 → 0.7.0-staging.36121841659

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 CHANGED
@@ -41,7 +41,11 @@ npx shipyard init
41
41
 
42
42
  During `shipyard init`, choose your agent, **Docker**, the template you want, and install the optional
43
43
  [repository runner](docs/content/docs/repository-runner.mdx). Follow
44
- the authentication prompts.
44
+ the authentication prompts. Init offers to commit and push the generated
45
+ Shipyard setup to the current branch. The offer stages `.shipyard/` and, when
46
+ installed, `.github/workflows/shipyard-wake.yml`. It leaves `.shipyard/.env`
47
+ untracked. Non-interactive init skips the offer; pass `--commit-setup true` to
48
+ commit and push the generated files.
45
49
 
46
50
  On a local Mac, the repository runner automatically wakes Shipyard when you label an issue.
47
51
  It runs as long as its terminal stays open.
@@ -60,8 +64,8 @@ conflict resolution, and integration. The review-enabled planner also uses
60
64
  strong for ticket and final specification reviews. See
61
65
  [agent setup](docs/content/docs/agents.mdx).
62
66
 
63
- Commit the setup and prompt so the sandbox can read them. Make sure the Git ignore file keeps
64
- `.shipyard/.env` out of the commit.
67
+ If you decline the commit, commit `.shipyard/` before running Shipyard. Docker
68
+ sandboxes read setup files from Git history. Keep `.shipyard/.env` untracked.
65
69
 
66
70
  ```sh
67
71
  npx shipyard run
package/dist/main.js CHANGED
@@ -271,8 +271,7 @@ var ISSUE_TRACKER_REGISTRY = [
271
271
  # Required repository permissions: Contents, Issues, and Pull requests (Read and write); Metadata (Read)
272
272
  # Or leave blank and run: GH_TOKEN="$(gh auth token)" npx shipyard run
273
273
  GH_TOKEN=
274
- # GitHub repository (owner/repository)
275
- GH_REPO=`
274
+ `
276
275
  }
277
276
  ];
278
277
  var listIssueTrackers = () => ISSUE_TRACKER_REGISTRY;
@@ -358,8 +357,8 @@ var rewriteMainTs = (configDir, agent, model, modelExplicit, sandboxProvider, ma
358
357
  }
359
358
  if (agent.name === "codex" && codexAuth === "chatgpt") {
360
359
  content = content.replace(
361
- /\bdocker\(\)/g,
362
- `docker(${CODEX_CHATGPT_AUTH_OPTIONS})`
360
+ "const sandboxAuthOptions = {};",
361
+ `const sandboxAuthOptions = ${CODEX_CHATGPT_AUTH_OPTIONS};`
363
362
  );
364
363
  }
365
364
  content = content.replace(/\bdocker\b/g, sandboxProvider.name);
@@ -1293,12 +1292,57 @@ var initializeRepositoryRunner = async (options) => {
1293
1292
  }
1294
1293
  };
1295
1294
  var repositoryRunnerNextSteps = () => [
1296
- `First, commit and push ${REPOSITORY_RUNNER_WORKFLOW_PATH} to the repository's default branch`,
1295
+ `Ensure ${REPOSITORY_RUNNER_WORKFLOW_PATH} is committed and pushed to the repository's default branch`,
1297
1296
  `Keep the foreground controller open with \`npx ${CLI_NAME} runner start\``,
1298
1297
  `Inspect it from another terminal with \`npx ${CLI_NAME} runner status\``,
1299
1298
  `Stop it with \`npx ${CLI_NAME} runner stop\``,
1300
1299
  `Unregister and delete its protected files with \`npx ${CLI_NAME} runner remove\``
1301
1300
  ];
1301
+ var errorText = (error) => {
1302
+ if (error !== null && typeof error === "object" && "stderr" in error) {
1303
+ const stderr = error.stderr;
1304
+ if (typeof stderr === "string" || Buffer.isBuffer(stderr)) {
1305
+ const text = stderr.toString().trim();
1306
+ if (text) return text;
1307
+ }
1308
+ }
1309
+ return error instanceof Error ? error.message : String(error);
1310
+ };
1311
+ var commitAndPushInitSetup = (repoDir) => {
1312
+ const branch = execFileSync("git", ["branch", "--show-current"], {
1313
+ cwd: repoDir,
1314
+ encoding: "utf8"
1315
+ }).trim();
1316
+ if (!branch) {
1317
+ throw new Error("Cannot push the Shipyard setup from a detached HEAD.");
1318
+ }
1319
+ const paths = [CONFIG_DIR];
1320
+ if (existsSync(join(repoDir, REPOSITORY_RUNNER_WORKFLOW_PATH))) {
1321
+ paths.push(REPOSITORY_RUNNER_WORKFLOW_PATH);
1322
+ }
1323
+ execFileSync("git", ["add", "--", ...paths], {
1324
+ cwd: repoDir,
1325
+ stdio: "ignore"
1326
+ });
1327
+ execFileSync(
1328
+ "git",
1329
+ ["commit", "--only", "-m", "Add Shipyard setup", "--", ...paths],
1330
+ { cwd: repoDir, stdio: "pipe" }
1331
+ );
1332
+ const commit = execFileSync("git", ["rev-parse", "--short", "HEAD"], {
1333
+ cwd: repoDir,
1334
+ encoding: "utf8"
1335
+ }).trim();
1336
+ try {
1337
+ execFileSync("git", ["push", "origin", `HEAD:refs/heads/${branch}`], {
1338
+ cwd: repoDir,
1339
+ stdio: "pipe"
1340
+ });
1341
+ return { branch, commit };
1342
+ } catch (error) {
1343
+ return { branch, commit, pushError: errorText(error) };
1344
+ }
1345
+ };
1302
1346
  var execFileAsync2 = promisify(execFile);
1303
1347
  var CONTROLLER_STATE = ".shipyard-state.json";
1304
1348
  var LAST_FAILURE = ".shipyard-last-failure.json";
@@ -2367,7 +2411,7 @@ var runnerCommand = Command.make(
2367
2411
  purgeRunnerCommand
2368
2412
  ])
2369
2413
  );
2370
- var VERSION = "0.7.0-staging.36082887921" ;
2414
+ var VERSION = "0.7.0-staging.36121841659" ;
2371
2415
 
2372
2416
  // src/cli.ts
2373
2417
  var imageNameOption = Options.text("image-name").pipe(
@@ -2588,6 +2632,11 @@ var installRunnerOption = Options.choice("install-runner", [
2588
2632
  ),
2589
2633
  Options.optional
2590
2634
  );
2635
+ var commitSetupOption = Options.choice("commit-setup", ["true", "false"]).pipe(
2636
+ Options.withDescription(
2637
+ "Whether to commit and push .shipyard/ and the optional runner workflow"
2638
+ )
2639
+ ).pipe(Options.optional);
2591
2640
  var choiceToTriBool = (opt) => opt._tag === "Some" ? Option.some(opt.value === "true") : Option.none();
2592
2641
  var initCommand = Command.make(
2593
2642
  "init",
@@ -2601,7 +2650,8 @@ var initCommand = Command.make(
2601
2650
  issueTracker: issueTrackerOption,
2602
2651
  buildImage: buildImageOption,
2603
2652
  installTemplateDeps: installTemplateDepsOption,
2604
- installRunner: installRunnerOption
2653
+ installRunner: installRunnerOption,
2654
+ commitSetup: commitSetupOption
2605
2655
  },
2606
2656
  ({
2607
2657
  imageName: imageNameFlag,
@@ -2613,7 +2663,8 @@ var initCommand = Command.make(
2613
2663
  issueTracker: issueTrackerFlag,
2614
2664
  buildImage: buildImageFlag,
2615
2665
  installTemplateDeps: installTemplateDepsFlag,
2616
- installRunner: installRunnerFlag
2666
+ installRunner: installRunnerFlag,
2667
+ commitSetup: commitSetupFlag
2617
2668
  }) => Effect.gen(function* () {
2618
2669
  const d = yield* Display;
2619
2670
  const cwd = process.cwd();
@@ -2657,6 +2708,7 @@ var initCommand = Command.make(
2657
2708
  installTemplateDepsFlag
2658
2709
  );
2659
2710
  const installRunnerChoice = choiceToTriBool(installRunnerFlag);
2711
+ const commitSetupChoice = choiceToTriBool(commitSetupFlag);
2660
2712
  const isInteractive = process.stdin.isTTY === true;
2661
2713
  const failIfNonInteractive = (flag) => Effect.fail(
2662
2714
  new InitError({
@@ -2966,15 +3018,12 @@ var initCommand = Command.make(
2966
3018
  message: `Repository-runner setup failed: ${error instanceof Error ? error.message : String(error)}`
2967
3019
  })
2968
3020
  });
2969
- if (runnerInit.status === "installed") {
3021
+ const runnerInstalled = runnerInit.status === "installed";
3022
+ if (runnerInstalled) {
2970
3023
  yield* d.status(
2971
3024
  `Installed ${runnerInit.result.name} for ${runnerInit.result.repository}.`,
2972
3025
  "success"
2973
3026
  );
2974
- yield* d.text("Repository runner next steps:");
2975
- for (const [index, line] of repositoryRunnerNextSteps().entries()) {
2976
- yield* d.text(styleText("dim", `${index + 1}. ${line}`));
2977
- }
2978
3027
  } else if (runnerInit.status === "failed") {
2979
3028
  yield* d.status(
2980
3029
  `Shipyard scaffolding is ready, but repository runner installation failed: ${runnerInit.message}`,
@@ -2985,6 +3034,77 @@ var initCommand = Command.make(
2985
3034
  "warn"
2986
3035
  );
2987
3036
  }
3037
+ let shouldCommitSetup = commitSetupChoice._tag === "Some" && commitSetupChoice.value;
3038
+ if (commitSetupChoice._tag === "None" && isInteractive) {
3039
+ const confirmed = yield* Effect.promise(
3040
+ () => clack2.confirm({
3041
+ message: "Commit .shipyard/ and the optional runner workflow, then push this branch to origin? Sandboxes need the setup committed. The push also sends any local commits not already on origin.",
3042
+ initialValue: true
3043
+ })
3044
+ );
3045
+ if (clack2.isCancel(confirmed)) {
3046
+ yield* Effect.fail(
3047
+ new InitError({ message: "Shipyard setup commit cancelled." })
3048
+ );
3049
+ }
3050
+ shouldCommitSetup = confirmed === true;
3051
+ }
3052
+ if (shouldCommitSetup) {
3053
+ const publishResult = yield* Effect.sync(() => {
3054
+ try {
3055
+ return {
3056
+ status: "committed",
3057
+ result: commitAndPushInitSetup(cwd)
3058
+ };
3059
+ } catch (error) {
3060
+ return {
3061
+ status: "failed",
3062
+ message: error instanceof Error ? error.message : String(error)
3063
+ };
3064
+ }
3065
+ });
3066
+ if (publishResult.status === "failed") {
3067
+ yield* d.status(
3068
+ `Could not commit the Shipyard setup: ${publishResult.message}`,
3069
+ "warn"
3070
+ );
3071
+ yield* d.status(
3072
+ `Commit \`${CONFIG_DIR}/\` before running Shipyard.`,
3073
+ "warn"
3074
+ );
3075
+ } else if (publishResult.result.pushError) {
3076
+ yield* d.status(
3077
+ `Committed ${publishResult.result.commit}, but could not push to origin/${publishResult.result.branch}: ${publishResult.result.pushError}`,
3078
+ "warn"
3079
+ );
3080
+ yield* d.status(
3081
+ `Push it later with \`git push origin ${publishResult.result.branch}\`.`,
3082
+ "warn"
3083
+ );
3084
+ } else {
3085
+ yield* d.status(
3086
+ `Committed ${publishResult.result.commit} and pushed origin/${publishResult.result.branch}.`,
3087
+ "success"
3088
+ );
3089
+ }
3090
+ } else {
3091
+ yield* d.status(
3092
+ `Commit \`${CONFIG_DIR}/\` before running Shipyard. Sandboxes do not receive uncommitted setup files.`,
3093
+ "warn"
3094
+ );
3095
+ if (runnerInstalled) {
3096
+ yield* d.status(
3097
+ "Push the runner wake workflow to the repository's default branch before starting the runner.",
3098
+ "warn"
3099
+ );
3100
+ }
3101
+ }
3102
+ if (runnerInstalled) {
3103
+ yield* d.text("Repository runner next steps:");
3104
+ for (const [index, line] of repositoryRunnerNextSteps().entries()) {
3105
+ yield* d.text(styleText("dim", `${index + 1}. ${line}`));
3106
+ }
3107
+ }
2988
3108
  yield* d.status("Init complete!", "success");
2989
3109
  const nextSteps = getNextStepsLines();
2990
3110
  for (const [i, line] of nextSteps.entries()) {