turnzero 0.27.0 → 0.30.0

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.
@@ -37,7 +37,7 @@ var shownHealthPathOf = (path) => {
37
37
  }
38
38
  return JSON.stringify("\u2026");
39
39
  };
40
- var healthPathUnservedDetail = (path) => `No source text in the zip names the health path ${shownHealthPathOf(path)}. Serve it from your code, or set the manifest's health to a served path and call submit_manifest (PLD-L0-63).`;
40
+ var healthPathUnservedDetail = (path) => `No source text in the zip names the health path ${shownHealthPathOf(path)}. Serve it from your code, or set the manifest's health to a served path and call submit_manifest.`;
41
41
  var deployAreaName = (application) => `${DEPLOY_AREA_PREFIX}${application}`;
42
42
  var UPLOAD_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
43
43
  var uploadFileName = (id) => `${id}.zip`;
@@ -275,6 +275,11 @@ var MINT_TOKEN_ACTION = "mint_token";
275
275
  var REVOKE_TOKEN_ACTION = "revoke_token";
276
276
  var AUTHORIZED_LINE_HEAD = "authorized: ";
277
277
  var LOGGED_OUT_LINE_HEAD = "logged out: ";
278
+ var COMPLETION_MEMBER = "completion";
279
+ var COMPLETION_MINT = "mint";
280
+ var MINT_MEMBER = "mint";
281
+ var MINT_OPTION = "--mint";
282
+ var MINT_ID_FORM = UPLOAD_ID;
278
283
 
279
284
  // src/turnzero_cloud_command/credential_file.ts
280
285
  import { randomBytes } from "node:crypto";
@@ -393,14 +398,14 @@ var isWireVersion = (value) => parseWireVersion(value) !== null;
393
398
  function compareWireVersions(a, b) {
394
399
  const x2 = parseWireVersion(a);
395
400
  const y = parseWireVersion(b);
396
- if (!x2 || !y) throw new Error("a wire version is a date, a dot, and a counter (MAPI-02).");
401
+ if (!x2 || !y) throw new Error("a wire version is a date, a dot, and a counter.");
397
402
  if (x2.date !== y.date) return x2.date < y.date ? -1 : 1;
398
403
  return x2.counter === y.counter ? 0 : x2.counter < y.counter ? -1 : 1;
399
404
  }
400
405
 
401
406
  // src/turnzero_cloud_command/plane_wire.ts
402
407
  var PLANE_WIRE_NEEDED = Object.freeze({
403
- action_payloads: "2026-10-14.2",
408
+ action_payloads: "2026-10-24.10",
404
409
  management_api: "2026-10-10.5",
405
410
  wire_errors: "2026-10-10.6"
406
411
  });
@@ -440,19 +445,20 @@ var originReadOf = (value) => {
440
445
  const held = (value ?? "").trim();
441
446
  return held === "" ? DEFAULT_COMMAND_ORIGIN : originOf(held) ?? held;
442
447
  };
448
+ var ORIGIN_FORM_SENTENCES = `It is an https address with no path, ${ORIGIN_HOST_WORDS}. For a local platform, it may be an http address of this machine: 127.0.0.1, localhost, or [::1].`;
443
449
  var commandOriginOf = (text) => {
444
450
  const origin = originOf(text);
445
451
  if (origin !== null) return { origin };
446
452
  return {
447
- refusal: `${DEPLOY_OPTION.origin} names the platform's address, such as ${DEFAULT_COMMAND_ORIGIN}: an https address with no path, ${ORIGIN_HOST_WORDS}, or an http address of this machine (127.0.0.1, localhost, or [::1]) for a local platform, since the command sends its credential to it. Nothing was started.`
453
+ refusal: `${DEPLOY_OPTION.origin} names the platform's address, such as ${DEFAULT_COMMAND_ORIGIN}, since the command sends its credential to it. ${ORIGIN_FORM_SENTENCES} Nothing was started.`
448
454
  };
449
455
  };
450
456
  var MINTED_TOKEN_OUTSIDE_OPENING = `${DEPLOY_OPTION.origin} names an address this run does not send its minted token to.`;
451
457
  var firstPartyOriginWayOn = (origin) => `Set ${ORIGIN_VARIABLE} to ${origin} beside ${MINTED_TOKEN_VARIABLE} and run the line again, since that variable, never the line, states where the minted token goes.`;
452
- var MINTED_TOKEN_HELD_ALONE = `${MINTED_TOKEN_OUTSIDE_OPENING} Where ${ORIGIN_VARIABLE} is set, a line run by a tool connected by a minted token, or by a job, sends the token in ${MINTED_TOKEN_VARIABLE} only to the address that variable holds, so ${DEPLOY_OPTION.origin} may name that address alone. Where the platform is at another address, set ${ORIGIN_VARIABLE} to it beside the token, or unset the variable for the command's default address, and run the line again.`;
458
+ var MINTED_TOKEN_HELD_ALONE = `${MINTED_TOKEN_OUTSIDE_OPENING} Where ${ORIGIN_VARIABLE} is set, a line run by a tool connected by a minted token, or by a job, sends the token in ${MINTED_TOKEN_VARIABLE} only to the address that variable holds. The line's ${DEPLOY_OPTION.origin} may then name that address alone. Where the platform is at another address, set ${ORIGIN_VARIABLE} to it beside the token, or unset the variable for the command's default address, and run the line again.`;
453
459
  var mintedTokenOriginOf = (env, named, closing) => {
454
460
  const held = heldOriginOf(env, named, closing, {
455
- variable: "a line run by a tool connected by a minted token, or by a job, sends the minted token to the address the variable names",
461
+ variable: "A line run by a tool connected by a minted token, or by a job, sends the minted token to the address the variable names",
456
462
  outside: `${MINTED_TOKEN_OUTSIDE_OPENING} A line run by a tool connected by a minted token, or by a job, sends the token in ${MINTED_TOKEN_VARIABLE} only to ${DEFAULT_COMMAND_ORIGIN} or to the address ${ORIGIN_VARIABLE} holds in the same environment. Where the platform is at another address, set ${ORIGIN_VARIABLE} to it beside the token, and run the line again.`,
457
463
  heldAlone: MINTED_TOKEN_HELD_ALONE
458
464
  });
@@ -466,7 +472,7 @@ var heldOriginOf = (env, named, closing, words) => {
466
472
  const fromEnvironment = held === "" ? null : originOf(held);
467
473
  if (held !== "" && fromEnvironment === null) {
468
474
  return {
469
- refusal: `What ${ORIGIN_VARIABLE} holds is not the platform's address: ${words.variable}, such as ${DEFAULT_COMMAND_ORIGIN}, which is an https address with no path, ${ORIGIN_HOST_WORDS}, or an http address of this machine (127.0.0.1, localhost, or [::1]) for a local platform. Set the variable to that address, or unset it. ${closing}`
475
+ refusal: `What ${ORIGIN_VARIABLE} holds is not the platform's address. ${words.variable}, such as ${DEFAULT_COMMAND_ORIGIN}. ${ORIGIN_FORM_SENTENCES} Set the variable to that address, or unset it. ${closing}`
470
476
  };
471
477
  }
472
478
  if (named === void 0) return { origin: fromEnvironment ?? DEFAULT_COMMAND_ORIGIN };
@@ -481,7 +487,7 @@ var heldOriginOf = (env, named, closing, words) => {
481
487
  var AUTHORIZATION_ACTS_WORDS = `${AUTHORIZE_SUBCOMMAND}, ${TOKEN_SUBCOMMAND} ${TOKEN_REQUEST_ACT}, and ${TOKEN_SUBCOMMAND} ${TOKEN_CLAIM_ACT}`;
482
488
  var authorizationOriginOf = (env, named, closing) => heldOriginOf(env, named, closing, {
483
489
  variable: `${AUTHORIZATION_ACTS_WORDS} reach only the address the variable names`,
484
- outside: `${DEPLOY_OPTION.origin} names an address this computer's authorization does not reach: ${AUTHORIZATION_ACTS_WORDS} reach only ${DEFAULT_COMMAND_ORIGIN}, ${DEVELOPMENT_COMMAND_ORIGIN}, or the address ${ORIGIN_VARIABLE} holds, so a line chooses only between the platform's own two addresses and the environment names any other. Where the platform is at another address, set ${ORIGIN_VARIABLE} to it, and run the line again.`,
490
+ outside: `${DEPLOY_OPTION.origin} names an address this computer's authorization does not reach. ${AUTHORIZATION_ACTS_WORDS} reach only ${DEFAULT_COMMAND_ORIGIN}, ${DEVELOPMENT_COMMAND_ORIGIN}, or the address ${ORIGIN_VARIABLE} holds. A line chooses only between the platform's own two addresses, and the environment names any other. Where the platform is at another address, set ${ORIGIN_VARIABLE} to it, and run the line again.`,
485
491
  admitted: FIRST_PARTY_COMMAND_ORIGINS
486
492
  });
487
493
  var entryOriginOf = (env, named, closing) => {
@@ -491,7 +497,7 @@ var entryOriginOf = (env, named, closing) => {
491
497
  const origin = originOf(held);
492
498
  if (origin !== null) return { origin };
493
499
  return {
494
- refusal: `What ${ORIGIN_VARIABLE} holds is not the platform's address: where the line names no ${DEPLOY_OPTION.origin}, the command reads this computer's entry for the address the variable names, such as ${DEFAULT_COMMAND_ORIGIN}, which is an https address with no path, ${ORIGIN_HOST_WORDS}, or an http address of this machine (127.0.0.1, localhost, or [::1]) for a local platform. Set the variable to that address, or unset it. ${closing}`
500
+ refusal: `What ${ORIGIN_VARIABLE} holds is not the platform's address. Where the line names no ${DEPLOY_OPTION.origin}, the command reads this computer's entry for the address the variable names, such as ${DEFAULT_COMMAND_ORIGIN}. ${ORIGIN_FORM_SENTENCES} Set the variable to that address, or unset it. ${closing}`
495
501
  };
496
502
  };
497
503
  var HEADER_VALUE = /^[\x20-\x7e]*$/;
@@ -551,7 +557,7 @@ var WIRE_FILE_NOUNS = Object.freeze({
551
557
  });
552
558
  var PLANE_OLDER_WAY_ON = "Nothing was started: run this command again once the origin serves a newer release.";
553
559
  var PLANE_OLDER_FIRST_ACT_WAY_ON = "Nothing was started: once the origin serves a newer release, start again with the first act.";
554
- var planeOlderSentence = (version, origin, key, needs, served, tokenCodeUnread) => `${TURNZERO_CLOUD_PACKAGE} ${version} needs ${WIRE_FILE_NOUNS[key]} of ${needs} or later, and ${origin} serves ${served}, an older Turn Zero Cloud. ${tokenCodeUnread === void 0 ? PLANE_OLDER_WAY_ON : `${PLANE_OLDER_FIRST_ACT_WAY_ON} ${tokenCodeUnread}`}`;
560
+ var planeOlderSentence = (version, origin, key, needs, served, tokenCodeUnread) => `${TURNZERO_CLOUD_PACKAGE} ${version} needs ${WIRE_FILE_NOUNS[key]} of ${needs} or later, and ${origin} serves ${served}, an older Turn Zero Cloud. ${tokenCodeUnread === void 0 ? PLANE_OLDER_WAY_ON : tokenCodeUnread === "" ? PLANE_OLDER_FIRST_ACT_WAY_ON : `${PLANE_OLDER_FIRST_ACT_WAY_ON} ${tokenCodeUnread}`}`;
555
561
  var COMMAND_LATEST_FORM = /^(?:0|[1-9]\d{0,8})\.(?:0|[1-9]\d{0,8})\.(?:0|[1-9]\d{0,8})$/;
556
562
  var servedHealthOf = async (io2, origin) => {
557
563
  const controller = new AbortController();
@@ -845,7 +851,8 @@ var loginLinesFor = (io2, origin) => [
845
851
  var REDACTED_TOKEN = "<minted token>";
846
852
  var MINTED_TOKEN_PREFIX_WORDS = `${MINTED_TOKEN_PREFIX.slice(0, -1)} and an underscore`;
847
853
  var CREDENTIAL_SOURCES = Object.freeze(["standard_input", "minted_token_variable", "credential_file"]);
848
- var credentialPlaces = (declared) => declared.places ?? `the command reads the grant from its standard input, as the line ${declared.call} answers pipes it in${declared.mintedToken ? `, and otherwise a minted token from ${MINTED_TOKEN_VARIABLE} where it is set, or this computer's token for the platform's address from its credential file, which login and authorize write` : declared.computerToken === true ? `, and otherwise this computer's token for the platform's address from its credential file, which login and authorize write, and never a minted token from ${MINTED_TOKEN_VARIABLE}` : ""}.`;
854
+ var NO_INPUT_PLACES = `The command reads no standard input. It reads a minted token from ${MINTED_TOKEN_VARIABLE} where it is set. A tool connected by a minted token sets it from where its token is kept, and a job with no tool from its secret store. Otherwise it reads this computer's token for the platform's address from its credential file, which login and authorize write.`;
855
+ var credentialPlaces = (declared) => declared.places ?? `The command reads the grant from its standard input, as the line ${declared.call} answers pipes it in.${declared.mintedToken ? ` Otherwise it reads a minted token from ${MINTED_TOKEN_VARIABLE} where it is set, or this computer's token for the platform's address from its credential file, which login and authorize write.` : declared.computerToken === true ? ` Otherwise it reads this computer's token for the platform's address from its credential file, which login and authorize write. It never reads a minted token from ${MINTED_TOKEN_VARIABLE}.` : ""}`;
849
856
  var unsetVariableWayOn = (declared) => `To run a line you wrote yourself under this computer's token, unset ${MINTED_TOKEN_VARIABLE} and run it again; or pipe ${declared.aGrant}.`;
850
857
  var grantWaysOn = (declared) => `Pipe ${declared.aGrant}, as the line ${declared.call} answers pipes it, or, where you wrote the line yourself, pipe nothing to run it under this computer's token.`;
851
858
  var emptyGrantRefusal = (declared) => `The ${declared.grant} piped to the command was empty, so nothing was sent and nothing was started. ${grantWaysOn(declared)}`;
@@ -856,7 +863,7 @@ var unendedReadRefusal = (declared, reading) => unendedReadSentence(
856
863
  declared.computerToken === true ? grantWaysOn(declared) : pipeWholeWayOn(declared.aGrant, declared.call)
857
864
  );
858
865
  var emptyTokenVariableRefusal = () => `${MINTED_TOKEN_VARIABLE} is set but empty, so nothing was sent and nothing was started: the read that set it for this line found no token. Set it to your minted token from where your tool keeps it, or unset it to use this computer's token.`;
859
- var noCredentialRefusal = (declared, origin, expiredAt, again) => `No ${declared.grant} was read, so nothing was started: ${credentialPlaces(declared)} ${expiredAt === null ? `This computer's credential file holds no token for ${origin}.` : `This computer's token for ${origin} in its credential file expired at ${expiredAt}.`} ${again}`.trimEnd();
866
+ var noCredentialRefusal = (declared, origin, expiredAt, again) => `No ${declared.grant} was read, so nothing was started. ${credentialPlaces(declared)} ${expiredAt === null ? `This computer's credential file holds no token for ${origin}.` : `This computer's token for ${origin} in its credential file expired at ${expiredAt}.`} ${again}`.trimEnd();
860
867
  var expired = (expiresAt, now) => expiresAt !== null && Date.parse(expiresAt) <= now.getTime();
861
868
  async function readCredential(io2, declared, again, line = { named: void 0, closing: "" }) {
862
869
  if (declared.piped !== false) {
@@ -880,14 +887,14 @@ async function readCredential(io2, declared, again, line = { named: void 0, clos
880
887
  if (held !== void 0 && token2 === "" && declared.mintedToken) return { refusal: emptyTokenVariableRefusal() };
881
888
  if (token2 !== "" && !declared.mintedToken) {
882
889
  return {
883
- refusal: `No ${declared.grant} was read, so nothing was started. ${MINTED_TOKEN_VARIABLE} is set, and this subcommand does not run under a minted token: ${credentialPlaces(declared)} ${computerToken ? `${unsetVariableWayOn(declared)} ` : ""}${again}`
890
+ refusal: `No ${declared.grant} was read, so nothing was started. ${MINTED_TOKEN_VARIABLE} is set, and this subcommand does not run under a minted token. ${credentialPlaces(declared)} ${computerToken ? `${unsetVariableWayOn(declared)} ` : ""}${again}`
884
891
  };
885
892
  }
886
- if (!declared.mintedToken && !computerToken) return { refusal: `No ${declared.grant} was read, so nothing was started: ${credentialPlaces(declared)} ${again}` };
893
+ if (!declared.mintedToken && !computerToken) return { refusal: `No ${declared.grant} was read, so nothing was started. ${credentialPlaces(declared)} ${again}` };
887
894
  if (token2 !== "") {
888
895
  if (!MINTED_TOKEN_FORM.test(token2)) {
889
896
  return {
890
- refusal: `What ${MINTED_TOKEN_VARIABLE} holds is not a minted token, so nothing was sent and nothing was started: a token mint_token answers opens with ${MINTED_TOKEN_PREFIX_WORDS}. Set the variable to that token, from where your tool keeps it or from your CI's secret store.`
897
+ refusal: `${MINTED_TOKEN_VARIABLE} does not hold a minted token, so nothing was sent and nothing was started. A token that mint_token answers opens with ${MINTED_TOKEN_PREFIX_WORDS}. Set the variable to that token, from where your tool keeps it or from your CI's secret store.`
891
898
  };
892
899
  }
893
900
  return { credential: token2, kind: "token", source: "minted_token_variable" };
@@ -922,18 +929,19 @@ var variableReadSentence = (origin, standing) => {
922
929
  const opening = `The credential this run read was the minted token in ${MINTED_TOKEN_VARIABLE}, which wins over this computer's credential file`;
923
930
  switch (standing) {
924
931
  case "live":
925
- return `${opening}, and that file holds a token for ${origin}: where the variable is left from another run, unset it and run the line again to run under this computer's token.`;
932
+ return `${opening}. That file holds a token for ${origin}. Where the variable is left from another run, unset it and run the line again to run under this computer's token.`;
926
933
  case "expired":
927
- return `${opening}; that file holds a token for ${origin} that has expired.`;
934
+ return `${opening}. That file holds a token for ${origin} that has expired.`;
928
935
  case "none":
929
- return `${opening}; that file holds no token for ${origin}.`;
936
+ return `${opening}. That file holds no token for ${origin}.`;
930
937
  case "unread":
931
- return `${opening}; that file could not be read.`;
938
+ return `${opening}. That file could not be read.`;
932
939
  }
933
940
  };
934
941
  var fileReadSentence = (origin) => `The credential this run read was this computer's token for ${origin}, from its credential file: where the platform no longer accepts it, run ${LOGIN_SUBCOMMAND}${originWordsOf(origin)} to authorize this computer again.`;
935
942
  var noTokenSentence = (origin, expiredAt) => expiredAt === null ? `No credential was read, so nothing was sent: ${MINTED_TOKEN_VARIABLE} is not set, and this computer's credential file holds no token for ${origin}.` : `No credential was read, so nothing was sent: ${MINTED_TOKEN_VARIABLE} is not set, and this computer's token for ${origin} in its credential file expired at ${expiredAt}.`;
936
- var VARIABLE_ROUTE_SENTENCES = `A tool connected by a minted token, or a job, sets ${MINTED_TOKEN_VARIABLE} from where its token is kept, never by writing the value in a line, and ${ORIGIN_VARIABLE} to the address that minted the token where that is not ${DEFAULT_COMMAND_ORIGIN}, then runs the line again. Such a tool cannot use ${MINT_TOKEN_ACTION}, which takes a sign-in alone. A tool sets ${MINTED_TOKEN_VARIABLE} for one line at a time and unsets it once that line ends.`;
943
+ var VARIABLE_ROUTE_SENTENCES = `A tool connected by a minted token, or a job, sets ${MINTED_TOKEN_VARIABLE} from where its token is kept, never by writing the value in a line. It sets ${ORIGIN_VARIABLE} to the address that minted the token where that is not ${DEFAULT_COMMAND_ORIGIN}, then runs the line again. Such a tool cannot use ${MINT_TOKEN_ACTION}, which takes a sign-in alone. A tool sets ${MINTED_TOKEN_VARIABLE} for one line at a time and unsets it once that line ends.`;
944
+ var authorizeRouteSentence = (origin) => `${AUTHORIZE_SUBCOMMAND}${originWordsOf(origin)} run with nothing piped prints the ${MINT_TOKEN_ACTION} call a signed-in tool makes to authorize this computer.`;
937
945
  var LOGIN_ROUTE_OPENER = "A person logs this computer in once, in a terminal of their own, and its token then stays on this computer for 30 days:";
938
946
  var DEPLOY_FILES_ROUTE_SENTENCE = "A folder within the caps of your tool's deploy_files call deploys now through deploy_files, with no login.";
939
947
  var loginRouteLines = (io2, origin, deployFiles = true) => [
@@ -1010,7 +1018,9 @@ var TOKEN_CODE_RUN_AGAIN = "Run the line again once the cause above is put right
1010
1018
  var TOKEN_CODE_UNREAD = `${TOKEN_CODE_UNREAD_FIRST} ${TOKEN_CODE_RUN_AGAIN}`;
1011
1019
  var tokenCodeFloorSentence = (version, found) => `${TURNZERO_CLOUD_PACKAGE} ${version} needs Node.js ${COMMAND_NODE_FLOOR} or later, and this machine runs Node.js ${found}, so nothing was read and nothing was started. A token code the line carried was not read: it is live until it expires, and it mints nothing without this computer's verifier. Install Node.js ${COMMAND_NODE_FLOOR} or later, then run the line again.`;
1012
1020
  var NOTHING_SENT = "Nothing was sent and nothing was started.";
1013
- var carriesTokenCode = (argv2) => argv2[0] === AUTHORIZE_SUBCOMMAND || argv2[0] === TOKEN_SUBCOMMAND && argv2[1] === TOKEN_CLAIM_ACT;
1021
+ var MINT_UNPRESENTED = `Nothing was presented. ${TOKEN_CODE_RUN_AGAIN}`;
1022
+ var namesMint = (argv2) => argv2[0] === AUTHORIZE_SUBCOMMAND && argv2.slice(1).some((argument) => argument === MINT_OPTION || argument.startsWith(`${MINT_OPTION}=`));
1023
+ var carriesTokenCode = (argv2) => argv2[0] === AUTHORIZE_SUBCOMMAND && !namesMint(argv2) || argv2[0] === TOKEN_SUBCOMMAND && argv2[1] === TOKEN_CLAIM_ACT;
1014
1024
  var LABEL_FALLBACK = "authorized computer";
1015
1025
  var computerLabelOf = (host) => {
1016
1026
  let label = "";
@@ -1035,24 +1045,25 @@ var mintCallMembers = (kind, challenge, label) => kind === "authorized computer"
1035
1045
  [CODE_CHALLENGE_MEMBER, challenge],
1036
1046
  ["scope_kind", "account"],
1037
1047
  [AUTHORIZED_COMPUTER_MEMBER, true],
1038
- ["label", label]
1048
+ ["label", label],
1049
+ [COMPLETION_MEMBER, COMPLETION_MINT]
1039
1050
  ] : [[CODE_CHALLENGE_MEMBER, challenge]];
1040
1051
  var firstActNamed = (kind, origin = DEFAULT_COMMAND_ORIGIN) => `${kind === "authorized computer" ? AUTHORIZE_SUBCOMMAND : `${TOKEN_SUBCOMMAND} ${TOKEN_REQUEST_ACT}`}${originWordsOf(origin)}`;
1041
1052
  var noConnectionLine = (origin) => `Where your tool holds no connection signed in to ${origin}, ${MINT_TOKEN_ACTION} is not among its tools: a person connects the tool and signs in, in a browser, before the call.`;
1042
1053
  var loginWaySentence = (loginLines) => `A person can instead log this computer in themselves, in a terminal of their own, by running ${loginLines.join(", then ")}, and approving the login in the browser.`;
1043
1054
  var firstActLines = (origin, kind, pending, label, loginLines = []) => [
1044
- kind === "authorized computer" ? `To authorize this computer at ${origin}, call ${MINT_TOKEN_ACTION} from your tool, through the connection you signed in with, naming the members below and no others, then run the line it answers once, as given, on this computer.` : `To mint a token whose value never passes through the chat, call ${MINT_TOKEN_ACTION} at ${origin} from your tool, through the connection you signed in with, naming the member below beside the scope_kind, application, grants, label, and expires_in_days the task needs.`,
1055
+ kind === "authorized computer" ? `To authorize this computer at ${origin}, call ${MINT_TOKEN_ACTION} from your tool, through the connection you signed in with, naming the members below and no others. Then run the line it answers once, as given, on this computer.` : `To mint a token whose value never passes through the chat, call ${MINT_TOKEN_ACTION} at ${origin} from your tool, through the connection you signed in with. Name the member below beside the scope_kind, application, grants, label, and expires_in_days the task needs.`,
1045
1056
  // The case this command cannot see (#4273): a tool with no signed-in
1046
1057
  // connection holds no mint_token, and only a person's sign-in mends it.
1047
1058
  noConnectionLine(origin),
1048
1059
  `${CHALLENGE_LINE_HEAD}${pending.challenge}`,
1049
1060
  CALL_LINE_HEAD,
1050
1061
  ...mintCallMembers(kind, pending.challenge, label).map(([name, value]) => ` ${name}: ${JSON.stringify(value)}`),
1051
- kind === "authorized computer" ? `The line keeps the token it mints in this computer's credential file and revokes the one this computer held there before. The token is account-scoped and works from any computer until it expires or revoke_token ends it, and list_tokens shows it by its label. The request is pending until ${pending.expires_at}: ${firstActNamed(kind, origin)} run again before then prints this challenge again.` : `It answers a ${TOKEN_SUBCOMMAND} ${TOKEN_CLAIM_ACT} line, which is yours to run in a terminal outside the AI coding tool, on this computer as this user, and never through the tool: it prints the token's value once to standard output, so pipe it into your secret store's command where the token is a job's. The request is pending until ${pending.expires_at}: ${firstActNamed(kind, origin)} run again before then prints this challenge again.`,
1062
+ kind === "authorized computer" ? `The line it answers holds no code. It keeps the token it mints in this computer's credential file and revokes the one this computer held there before. The token is account-scoped and works from any computer until it expires or revoke_token ends it, and list_tokens shows it by its label. The request is pending until ${pending.expires_at}: ${firstActNamed(kind, origin)} run again before then prints this challenge again.` : `It answers a ${TOKEN_SUBCOMMAND} ${TOKEN_CLAIM_ACT} line, which is yours to run in a terminal outside the AI coding tool, on this computer as this user, and never through the tool. That line prints the token's value once to standard output, so pipe it into your secret store's command where the token is a job's. The request is pending until ${pending.expires_at}: ${firstActNamed(kind, origin)} run again before then prints this challenge again.`,
1052
1063
  ...kind === "authorized computer" && loginLines.length > 0 ? [loginWaySentence(loginLines)] : []
1053
1064
  ];
1054
1065
  var reusedRequestSentence = (origin, pending) => `A request for ${origin} is pending until ${pending.expires_at}, so its challenge is printed again and no new verifier was made.`;
1055
- var replacedRequestSentence = (origin, expired2) => `The request pending for ${origin} expired at ${expired2.expires_at}, so a new one replaces it: a line minted against the old challenge is refused at its exchange, and a ${MINT_TOKEN_ACTION} call naming the new challenge below answers a fresh one.`;
1066
+ var replacedRequestSentence = (origin, expired2) => `The request pending for ${origin} expired at ${expired2.expires_at}, so a new one replaces it. A line minted against the old challenge is refused at its exchange, and a ${MINT_TOKEN_ACTION} call naming the new challenge below answers a fresh one.`;
1056
1067
  async function firstAct(io2, origin, kind, say, opener = null) {
1057
1068
  const kept2 = keepPendingRequest(io2, origin, say);
1058
1069
  if ("status" in kept2) return kept2.status;
@@ -1115,6 +1126,7 @@ function keepPendingRequest(io2, origin, say) {
1115
1126
  var TOKEN_CALL_BOUND_SECONDS = 60;
1116
1127
  var EXCHANGE_ACT = "exchange";
1117
1128
  var exchangeBodyOf = (verifier) => ({ [CODE_VERIFIER_MEMBER]: verifier });
1129
+ var heldExchangeBodyOf = (mint) => ({ [MINT_MEMBER]: mint });
1118
1130
  var revocationBodyOf = (id) => ({ id });
1119
1131
  var postAction = async (io2, origin, action, bearer, userAgent, body) => {
1120
1132
  const controller = new AbortController();
@@ -1171,7 +1183,7 @@ var mintedTokenOf = (answer) => {
1171
1183
  };
1172
1184
  var mintAgainSentence = (kind, origin = DEFAULT_COMMAND_ORIGIN, login2 = null) => login2 !== null ? `Run ${login2} again to log this computer in.` : `Call ${MINT_TOKEN_ACTION} from your tool again with the challenge ${firstActNamed(kind, origin)} prints, and run the line it answers.`;
1173
1185
  var exchangeUnknownSentence = (kind, origin = DEFAULT_COMMAND_ORIGIN, login2 = null) => `Whether a token was minted is unknown: list_tokens from your tool shows each token by its label, and revoke_token ends one nothing holds. ${mintAgainSentence(kind, origin, login2)}`;
1174
- var noPendingSentence = (origin, kind) => `No request is pending for ${origin} on this computer, so the token code was not presented and nothing was sent: the verifier it needs is kept only on the computer whose ${firstActNamed(kind)} printed its challenge. Run ${firstActNamed(kind, origin)} on this computer, call ${MINT_TOKEN_ACTION} from your tool with the challenge it prints, and run the line it answers.`;
1186
+ var noPendingSentence = (origin, kind, presented = "code") => `No request is pending for ${origin} on this computer, so ${presented === "mint" ? "nothing was sent: the verifier the mint needs" : "the token code was not presented and nothing was sent: the verifier it needs"} is kept only on the computer whose ${firstActNamed(kind)} printed its challenge. Run ${firstActNamed(kind, origin)} on this computer, call ${MINT_TOKEN_ACTION} from your tool with the challenge it prints, and run the line it answers.`;
1175
1187
  var markerDisagreesSentence = (kind, origin = DEFAULT_COMMAND_ORIGIN) => kind === "authorized computer" ? `The exchange minted a token that is not an authorized computer's, and ${AUTHORIZE_SUBCOMMAND} keeps only an authorized computer's, so nothing of its value was printed or kept. Call ${MINT_TOKEN_ACTION} from your tool again naming ${AUTHORIZED_COMPUTER_MEMBER}: true, as ${AUTHORIZE_SUBCOMMAND} prints it, and run the line it answers.` : `The exchange minted an authorized computer's token, and ${TOKEN_SUBCOMMAND} ${TOKEN_CLAIM_ACT} prints only a token that is not one, so nothing of its value was printed or kept. Call ${MINT_TOKEN_ACTION} from your tool again without ${AUTHORIZED_COMPUTER_MEMBER}, as ${TOKEN_SUBCOMMAND} ${TOKEN_REQUEST_ACT} prints it, and run the line it answers; to authorize this computer, run ${AUTHORIZE_SUBCOMMAND}${originWordsOf(origin)}.`;
1176
1188
  var mintedRevocationLines = (revocation, minted) => "lines" in revocation ? [...revocation.lines, standsSentence(`The token it minted, ${minted.id},`, minted.id, minted.expiresAt)] : [`The token it minted, ${minted.id}, is revoked.`];
1177
1189
  var authorizedLineOf = (origin, entry, account = null) => `${AUTHORIZED_LINE_HEAD}${origin}${account !== null ? ` as ${accountWordsOf(account)}` : ""}, label ${entry.label !== null ? JSON.stringify(entry.label) : "none"}, its token expiring ${entry.expires_at !== null ? `at ${entry.expires_at}` : "never"}`;
@@ -1202,17 +1214,19 @@ async function readAccountUnder(io2, origin, token2, userAgent) {
1202
1214
  var whoamiLineFor = (io2, origin) => printedLineOf(io2, commandLineOf(origin, WHOAMI_SUBCOMMAND, origin !== DEFAULT_COMMAND_ORIGIN ? { origin } : {}), origin);
1203
1215
  var accountUnreadSentence = (whoami2) => `The account this computer's token acts as was not read, and the token is kept: run ${whoami2} to read it.`;
1204
1216
  var CLAIMED_LINE_HEAD = "claimed: ";
1205
- async function completeAct(io2, origin, kind, code, userAgent, say, deliver = () => void 0, login2 = null) {
1217
+ async function completeAct(io2, origin, kind, presentation, userAgent, say, deliver = () => void 0, login2 = null) {
1218
+ const held = "mint" in presentation;
1219
+ const unread = held ? MINT_UNPRESENTED : TOKEN_CODE_UNREAD;
1206
1220
  const place = credentialFileOf(io2);
1207
1221
  const read2 = readMovingCredentialFile(io2, place, say);
1208
1222
  if (!("state" in read2)) {
1209
- say(`${readRefusalOf(read2, place.path)} ${TOKEN_CODE_UNREAD}`);
1223
+ say(`${readRefusalOf(read2, place.path)} ${unread}`);
1210
1224
  return COMMAND_STATUS.nothing_started;
1211
1225
  }
1212
1226
  hideStandingTokens(io2, read2.state);
1213
1227
  const pending = read2.state.pending.get(origin);
1214
1228
  if (pending === void 0) {
1215
- say(noPendingSentence(origin, kind));
1229
+ say(noPendingSentence(origin, kind, held ? "mint" : "code"));
1216
1230
  return COMMAND_STATUS.nothing_started;
1217
1231
  }
1218
1232
  io2.hide(pending.verifier, REDACTED_VERIFIER);
@@ -1222,25 +1236,25 @@ async function completeAct(io2, origin, kind, code, userAgent, say, deliver = ()
1222
1236
  const release = io2.whenEnded(() => {
1223
1237
  stage.ended = true;
1224
1238
  say(
1225
- stage.now === "unsent" ? `The run was ended before its exchange. ${TOKEN_CODE_UNREAD}` : stage.now === "sent" ? `The run was ended during its exchange. ${exchangeUnknownSentence(kind, origin, login2)}` : `The run was ended after its exchange minted a token, which may not have been ${kind === "authorized computer" ? "kept" : "printed"}: list_tokens from your tool shows it by its label, and revoke_token ends it.`
1239
+ stage.now === "unsent" ? `The run was ended before its exchange. ${unread}` : stage.now === "sent" ? `The run was ended during its exchange. ${exchangeUnknownSentence(kind, origin, login2)}` : `The run was ended after its exchange minted a token, which may not have been ${kind === "authorized computer" ? "kept" : "printed"}: list_tokens from your tool shows it by its label, and revoke_token ends it.`
1226
1240
  );
1227
1241
  dropCredentialWriting(io2, place, tag);
1228
1242
  });
1229
1243
  try {
1230
1244
  const prepared = prepareCredentialFile(io2, place, tag);
1231
1245
  if ("unwritten" in prepared) {
1232
- say(`${unwritableFileSentence(place.path, prepared.unwritten)} Nothing was sent. ${TOKEN_CODE_UNREAD}`);
1246
+ say(`${unwritableFileSentence(place.path, prepared.unwritten)} Nothing was sent. ${unread}`);
1233
1247
  return COMMAND_STATUS.nothing_started;
1234
1248
  }
1235
1249
  if (stage.ended) return COMMAND_STATUS.nothing_started;
1236
- const older = await planeWireRefusal(io2, origin, TOKEN_CODE_UNREAD_FIRST);
1250
+ const older = await planeWireRefusal(io2, origin, held ? "" : TOKEN_CODE_UNREAD_FIRST);
1237
1251
  if (stage.ended) return COMMAND_STATUS.nothing_started;
1238
1252
  if (older !== null) {
1239
1253
  say(older);
1240
1254
  return COMMAND_STATUS.nothing_started;
1241
1255
  }
1242
1256
  stage.now = "sent";
1243
- const answered = await postAction(io2, origin, MINT_TOKEN_ACTION, code, userAgent, exchangeBodyOf(pending.verifier));
1257
+ const answered = "mint" in presentation ? await postAction(io2, origin, MINT_TOKEN_ACTION, pending.verifier, userAgent, heldExchangeBodyOf(presentation.mint)) : await postAction(io2, origin, MINT_TOKEN_ACTION, presentation.code, userAgent, exchangeBodyOf(pending.verifier));
1244
1258
  if (stage.ended) {
1245
1259
  const late = answered === null ? null : planeObjectOf(answered.text);
1246
1260
  if (late !== null && typeof late.value === "string") io2.hide(late.value, REDACTED_TOKEN);
@@ -1253,7 +1267,7 @@ async function completeAct(io2, origin, kind, code, userAgent, say, deliver = ()
1253
1267
  return COMMAND_STATUS.unknown;
1254
1268
  }
1255
1269
  if (answered.redirected) {
1256
- say(`The exchange was answered ${answeredHow(answered.status)}, which the command never follows, so the code and the verifier were sent to no second address.`);
1270
+ say(`The exchange was answered ${answeredHow(answered.status)}, which the command never follows, so ${held ? "the verifier was" : "the code and the verifier were"} sent to no second address.`);
1257
1271
  say(unknown);
1258
1272
  return COMMAND_STATUS.unknown;
1259
1273
  }
@@ -1272,7 +1286,9 @@ async function completeAct(io2, origin, kind, code, userAgent, say, deliver = ()
1272
1286
  return COMMAND_STATUS.unknown;
1273
1287
  }
1274
1288
  for (const line of refusalLines(EXCHANGE_ACT, answered.status, refusal)) say(line);
1275
- say(answered.status === 429 ? "Nothing was minted, and the token code was not spent: run the line again after the wait the answer names." : `Nothing was minted. ${mintAgainSentence(kind, origin, login2)}`);
1289
+ say(
1290
+ answered.status === 429 ? `Nothing was minted, and ${held ? "nothing was spent" : "the token code was not spent"}: run the line again after the wait the answer names.` : `Nothing was minted. ${mintAgainSentence(kind, origin, login2)}`
1291
+ );
1276
1292
  return COMMAND_STATUS.nothing_started;
1277
1293
  }
1278
1294
  const minted = answer === null ? null : mintedTokenOf(answer);
@@ -1344,29 +1360,45 @@ var AUTHORIZE_OPTIONS = Object.freeze([
1344
1360
  value: "<origin>",
1345
1361
  required: false,
1346
1362
  description: `The platform's address this computer is authorized at. Where absent, the address ${ORIGIN_VARIABLE} holds, or ${DEFAULT_COMMAND_ORIGIN} where it is unset. A ${DEPLOY_OPTION.origin} the line names must be ${DEFAULT_COMMAND_ORIGIN}, ${DEVELOPMENT_COMMAND_ORIGIN}, or the address ${ORIGIN_VARIABLE} holds, an address of this machine only where ${ORIGIN_VARIABLE} names it.`
1363
+ },
1364
+ {
1365
+ name: MINT_OPTION,
1366
+ value: "<id>",
1367
+ required: false,
1368
+ description: `The mint the line names, by its id, a lowercase UUID, as the line a ${MINT_TOKEN_ACTION} call answers names it. The id is no credential. Under it, ${AUTHORIZE_SUBCOMMAND} reads nothing on standard input and presents this computer's verifier for that mint.`
1347
1369
  }
1348
1370
  ]);
1371
+ var MINT_ID_REFUSAL = `${MINT_OPTION} names the mint by its id, a lowercase UUID, as the line the ${MINT_TOKEN_ACTION} call answered names it: run that line as given. ${NOTHING_SENT}`;
1349
1372
  var AUTHORIZE_CREDENTIAL = Object.freeze({
1350
1373
  grant: "token code",
1351
1374
  aGrant: "a token code",
1352
1375
  call: `the ${MINT_TOKEN_ACTION} call`,
1353
1376
  mintedToken: false,
1354
- bare: `with nothing piped, it keeps a verifier and prints the challenge and the ${MINT_TOKEN_ACTION} call that authorize this computer`
1377
+ pipes: `where the line pipes one in, as the line of a ${MINT_TOKEN_ACTION} call that sets no completion does`,
1378
+ bare: `with nothing piped and no ${MINT_OPTION}, it keeps a verifier and prints the challenge and the ${MINT_TOKEN_ACTION} call that authorize this computer. That call answers ${AUTHORIZE_SUBCOMMAND} ${MINT_OPTION} <id>, a line that holds no code: under it, ${AUTHORIZE_SUBCOMMAND} reads nothing on standard input and presents the verifier for that mint`
1355
1379
  });
1356
- var AUTHORIZATION_ORIGIN_VARIABLE_LINE = `the platform's address the authorization reaches where the line names no ${DEPLOY_OPTION.origin}, and the one address beside ${DEFAULT_COMMAND_ORIGIN} and ${DEVELOPMENT_COMMAND_ORIGIN} a ${DEPLOY_OPTION.origin} may name, an address of this machine only where it names it.`;
1380
+ var AUTHORIZATION_ORIGIN_VARIABLE_LINE = `the platform's address the authorization reaches where the line names no ${DEPLOY_OPTION.origin}. It is the one address beside ${DEFAULT_COMMAND_ORIGIN} and ${DEVELOPMENT_COMMAND_ORIGIN} a ${DEPLOY_OPTION.origin} may name, an address of this machine only where it names it.`;
1357
1381
  var CREDENTIAL_FILE_WORDS = `${CREDENTIAL_FILE_NAME} in a folder ${CREDENTIAL_FOLDER_NAME} under ${CONFIG_HOME_VARIABLE}, or under .config in your home folder where that is unset, readable by you alone. On Windows it is in a folder ${WINDOWS_CREDENTIAL_FOLDER_NAME} under your profile folder, ${PROFILE_VARIABLE}. A file under ${LOCAL_APP_DATA_VARIABLE} from an older version is moved there once`;
1358
- var AUTHORIZE_AFTER_OWN_ERROR = "a token code the line carried may not have been presented, and it is live until it expires and mints nothing without this computer's verifier; where a token was minted, list_tokens from your tool shows it by its label, and revoke_token ends it";
1382
+ var AUTHORIZE_AFTER_OWN_ERROR = "a token code the line carried may not have been presented. That code is live until it expires, and mints nothing without this computer's verifier. Where a token was minted, list_tokens from your tool shows it by its label, and revoke_token ends it";
1383
+ var MINT_AFTER_OWN_ERROR = "the verifier may not have been presented. Where a token was minted, list_tokens from your tool shows it by its label, and revoke_token ends it";
1359
1384
  async function authorize(call, io2) {
1385
+ const mint = call.named[MINT_OPTION];
1386
+ if (mint !== void 0 && !MINT_ID_FORM.test(mint)) {
1387
+ io2.print(MINT_ID_REFUSAL);
1388
+ return COMMAND_STATUS.nothing_started;
1389
+ }
1390
+ const unread = mint !== void 0 ? MINT_UNPRESENTED : TOKEN_CODE_UNREAD;
1360
1391
  const origin = authorizationOriginOf(io2.env, call.named[DEPLOY_OPTION.origin], NOTHING_SENT);
1361
1392
  if ("refusal" in origin) {
1362
- io2.print(`${origin.refusal} ${TOKEN_CODE_UNREAD}`);
1393
+ io2.print(`${origin.refusal} ${unread}`);
1363
1394
  return COMMAND_STATUS.nothing_started;
1364
1395
  }
1365
1396
  const agent = userAgentOf(io2.env);
1366
1397
  if ("refusal" in agent) {
1367
- io2.print(`${agent.refusal} ${TOKEN_CODE_UNREAD}`);
1398
+ io2.print(`${agent.refusal} ${unread}`);
1368
1399
  return COMMAND_STATUS.nothing_started;
1369
1400
  }
1401
+ if (mint !== void 0) return completeAct(io2, origin.origin, "authorized computer", { mint }, agent.userAgent, io2.print);
1370
1402
  const read2 = await readTokenCode(io2, "authorized computer", origin.origin);
1371
1403
  if ("refusal" in read2) {
1372
1404
  io2.print(read2.refusal);
@@ -1379,11 +1411,11 @@ async function authorize(call, io2) {
1379
1411
  return COMMAND_STATUS.nothing_started;
1380
1412
  }
1381
1413
  io2.hide(code, REDACTED_TOKEN_CODE);
1382
- return completeAct(io2, origin.origin, "authorized computer", code, agent.userAgent, io2.print);
1414
+ return completeAct(io2, origin.origin, "authorized computer", { code }, agent.userAgent, io2.print);
1383
1415
  }
1384
1416
  var AUTHORIZE_ROW = Object.freeze({
1385
1417
  name: AUTHORIZE_SUBCOMMAND,
1386
- summary: `Authorizes this computer at the platform's address, in two acts around one ${MINT_TOKEN_ACTION} call your tool makes. Run with nothing piped, it keeps a verifier in this computer's credential file, and prints the challenge and the call. Run with the token code the call's line pipes in, it presents the code with the verifier. It then keeps the token the platform mints in the credential file, and prints authorized:. It prints no token, code, or verifier.`,
1418
+ summary: `Authorizes this computer at the platform's address, in two acts around one ${MINT_TOKEN_ACTION} call your tool makes. Run with nothing piped, it keeps a verifier in this computer's credential file, and prints the challenge and the call. Run as the line the call answers, with ${MINT_OPTION} and no code, or with a piped token code, it presents the verifier. It then keeps the minted token in that file, and prints authorized:. It prints no token, code, or verifier.`,
1387
1419
  example: AUTHORIZE_SUBCOMMAND,
1388
1420
  options: AUTHORIZE_OPTIONS,
1389
1421
  credential: AUTHORIZE_CREDENTIAL,
@@ -1391,14 +1423,14 @@ var AUTHORIZE_ROW = Object.freeze({
1391
1423
  done: "the challenge printed, or this computer authorized",
1392
1424
  failed: "a token was minted and not kept, or the token this computer held before was not revoked: the printed lines name revoke_token",
1393
1425
  unknown: "the exchange drew no answer, or an answer that is not a refusal: list_tokens shows whether a token was minted",
1394
- nothing_started: "nothing was minted: an option, the credential file, or the token code was refused, no request was pending, the platform was too old, or the exchange was refused"
1426
+ nothing_started: `nothing was minted. An option, the mint's id, the credential file, or the token code was refused. Or no request was pending, the platform was too old, or the exchange was refused`
1395
1427
  },
1396
1428
  variables: [[ORIGIN_VARIABLE, AUTHORIZATION_ORIGIN_VARIABLE_LINE]],
1397
1429
  note: [
1398
- `Authorizing this computer takes three acts once for each platform address, which your signed-in tool makes itself and then reports to you; login, run in a terminal of your own, is your own way. ${AUTHORIZE_SUBCOMMAND} run with nothing piped prints a challenge and the ${MINT_TOKEN_ACTION} call to make; your tool makes that call through the connection you signed in with, and runs the line it answers once, as given, on this computer, which keeps the token.`,
1430
+ `Authorizing this computer takes three acts once for each platform address, which your signed-in tool makes itself and then reports to you; login, run in a terminal of your own, is your own way. ${AUTHORIZE_SUBCOMMAND} run with nothing piped prints a challenge and the ${MINT_TOKEN_ACTION} call to make. Your tool makes that call through the connection you signed in with, and runs the line it answers once, as given, on this computer. That line holds no code, and it keeps the token.`,
1399
1431
  `The token is account-scoped and works from any computer until it expires or revoke_token ends it: keep it as you would a password, list_tokens shows it by this computer's host name, and logout ends it. The credential file is ${CREDENTIAL_FILE_WORDS}.`
1400
1432
  ],
1401
- afterOwnError: AUTHORIZE_AFTER_OWN_ERROR,
1433
+ afterOwnError: (call) => call.named[MINT_OPTION] !== void 0 ? MINT_AFTER_OWN_ERROR : AUTHORIZE_AFTER_OWN_ERROR,
1402
1434
  run: authorize
1403
1435
  });
1404
1436
 
@@ -1865,11 +1897,11 @@ var codeOf = (error) => {
1865
1897
  return typeof code === "string" && /^[A-Z0-9_]+$/.test(code) ? code : "unwritable";
1866
1898
  };
1867
1899
  var addressable = (entry) => ![entry.area, ...entry.name.split(/[\\/]/)].some((segment) => segment === "." || segment === "..");
1868
- var applicationFolderSentence = () => `The folder the line runs in holds package.json, so it is an application's folder, and the line names no ${EXPORT_OPTION.path}: the export would be written inside it, where a deploy from that folder would carry every file of the export. Run the line again with ${EXPORT_OPTION.path} naming a folder outside this one, which the same grant serves until it expires. ${NOTHING_WRITTEN}`;
1900
+ var applicationFolderSentence = () => `The folder the line runs in holds package.json, so it is an application's folder, and the line names no ${EXPORT_OPTION.path}. The export would be written inside it, where a deploy from that folder would carry every file of the export. Run the line again with ${EXPORT_OPTION.path} naming a folder outside this one, which the same grant serves until it expires. ${NOTHING_WRITTEN}`;
1869
1901
  var ABSENT_FILE_STATUS = 404;
1870
1902
  var ABSENT_FILE_ERROR = "no_such_file";
1871
1903
  var freshExportLine = (absent) => `${absent === 1 ? "A file the manifest names was" : `${absent} files the manifest names were`} answered as an absent name and ${absent === 1 ? "was" : "were"} not read. A fresh export has the application's files as they now stand: call request_export from your tool, then ${DOWNLOAD_GRANT_ACTION} once read_export answers it completed.`;
1872
- var runAgainLine = (again) => `Run the line again before its grant expires, or take a fresh one: ${again} It skips the files on disk and reads again each file whose read failed.`;
1904
+ var runAgainLine = (again) => `Run the line again before its grant expires, or take a fresh one. ${again} It skips the files on disk and reads again each file whose read failed.`;
1873
1905
  var MANIFEST_READ = "The manifest read";
1874
1906
  var fileReadOf = (natural) => `The read of ${shownWhole(natural)}`;
1875
1907
  var APPLICATION_MARK = "package.json";
@@ -1917,7 +1949,7 @@ async function exportDownload(call, io2) {
1917
1949
  }
1918
1950
  if (earlier === null) {
1919
1951
  io2.print(
1920
- `${called} holds files and no index of this export, so the command writes nothing into it: name a new or empty folder with ${EXPORT_OPTION.path}, or the folder an earlier run of this export's line wrote. ${NOTHING_WRITTEN}`
1952
+ `${called} holds files and no index of this export, so the command writes nothing into it. Name a new or empty folder with ${EXPORT_OPTION.path}, or the folder an earlier run of this export's line wrote. ${NOTHING_WRITTEN}`
1921
1953
  );
1922
1954
  return COMMAND_STATUS.nothing_started;
1923
1955
  }
@@ -1986,7 +2018,7 @@ async function exportDownload(call, io2) {
1986
2018
  if (!(manifestRead instanceof Response)) {
1987
2019
  if (manifestRead.kind === "ended") for (const line of manifestRead.lines) io2.print(line);
1988
2020
  else io2.print(`The export's manifest could not be read: ${manifestRead.kind === "failed" ? manifestRead.reason : "the read was capped"}.`);
1989
- io2.print(`${manifestRead.kind === "ended" ? again : `Call read_export from your tool with application ${options.application} and export ${options.export} to see whether the export completed, then ${again.charAt(0).toLowerCase()}${again.slice(1)}`} ${NOTHING_WRITTEN}`);
2021
+ io2.print(`${manifestRead.kind === "ended" ? again : `Call read_export from your tool with application ${options.application} and export ${options.export} to see whether the export completed. Then ${again.charAt(0).toLowerCase()}${again.slice(1)}`} ${NOTHING_WRITTEN}`);
1990
2022
  return COMMAND_STATUS.nothing_started;
1991
2023
  }
1992
2024
  let manifestBytes;
@@ -2866,9 +2898,9 @@ function* readArtifactSteps(bytes) {
2866
2898
  const unreadable = () => new DeployRefusal(
2867
2899
  400,
2868
2900
  "artifact_unreadable",
2869
- "The artifact's bytes do not read as a zip archive. The platform deploys a zip holding the application's package.json at its root: zip the project folder's contents and deploy again (PLD-L0-63)."
2901
+ "The artifact's bytes do not read as a zip archive. The platform deploys a zip holding the application's package.json at its root: zip the project folder's contents and deploy again."
2870
2902
  );
2871
- const layoutRefusal = (detail) => new DeployRefusal(400, "artifact_layout_invalid", `${detail} (PLD-L0-63).`);
2903
+ const layoutRefusal = (detail) => new DeployRefusal(400, "artifact_layout_invalid", `${detail}.`);
2872
2904
  let declaredBytes = 0;
2873
2905
  let listing;
2874
2906
  try {
@@ -2909,7 +2941,7 @@ function* readArtifactSteps(bytes) {
2909
2941
  texts.set(index, inflateZipRecord(bytes, records[index]).toString("utf8"));
2910
2942
  } catch (error) {
2911
2943
  if (!(error instanceof ZipUnreadable)) throw error;
2912
- throw new DeployRefusal(400, "artifact_unreadable", `The zip's ${error.message}: zip the application's folder again, and deploy again (PLD-L0-63).`);
2944
+ throw new DeployRefusal(400, "artifact_unreadable", `The zip's ${error.message}: zip the application's folder again, and deploy again.`);
2913
2945
  }
2914
2946
  yield;
2915
2947
  }
@@ -2991,14 +3023,14 @@ function unbuiltBinding(reading) {
2991
3023
  }
2992
3024
  function artifactLayoutOf(reading) {
2993
3025
  const refuse = (detail) => {
2994
- throw new DeployRefusal(400, "artifact_layout_invalid", `${detail} (PLD-L0-63).`);
3026
+ throw new DeployRefusal(400, "artifact_layout_invalid", `${detail}.`);
2995
3027
  };
2996
3028
  const unbuilt = unbuiltBinding(reading);
2997
3029
  if (unbuilt !== null) {
2998
3030
  const where = unbuilt.root ? "is the root binding.gyp, and the zip holds no .node file outside node_modules and every workspace member's folder" : "is a binding.gyp of the artifact's own, beside a workspace member's package.json, and that member's folder, less its nested members' folders, holds no .node file";
2999
3031
  const ship = unbuilt.root ? "ship its .node file in the zip" : "ship its .node file inside the member's folder";
3000
3032
  refuse(
3001
- `The zip's entry ${shownEntry(unbuilt.entry)} ${where}. A native module of the artifact's own must ship prebuilt, because the platform never builds the customer's code (PLD-L0-60): build it for Linux on your machine, ${ship}, and deploy again`
3033
+ `The zip's entry ${shownEntry(unbuilt.entry)} ${where}. A native module of the artifact's own must ship prebuilt, because the platform never builds the customer's code: build it for Linux on your machine, ${ship}, and deploy again`
3002
3034
  );
3003
3035
  }
3004
3036
  if (reading.oversizedRoot !== null) {
@@ -3037,7 +3069,7 @@ var nestingDeeperThan = (value, max) => {
3037
3069
  function manifestCopyDepthRefusal(reading) {
3038
3070
  if (reading.manifestJson === null) return;
3039
3071
  if (nestingDeeperThan(parsePackageJson(reading.manifestJson), MANIFEST_COPY_DEPTH_MAX)) {
3040
- throw new DeployRefusal(400, "artifact_layout_invalid", `The zip's manifest.json nests deeper than the ${MANIFEST_COPY_DEPTH_MAX} levels the deploy reads: the platform reads the manifest submit_manifest recorded, so flatten the zip's copy or leave it out, and deploy again (PLD-L0-63).`);
3072
+ throw new DeployRefusal(400, "artifact_layout_invalid", `The zip's manifest.json nests deeper than the ${MANIFEST_COPY_DEPTH_MAX} levels the deploy reads: the platform reads the manifest submit_manifest recorded, so flatten the zip's copy or leave it out, and deploy again.`);
3041
3073
  }
3042
3074
  }
3043
3075
  function clientReadingOf(records) {
@@ -3057,7 +3089,7 @@ function clientReadingOf(records) {
3057
3089
  return { admitted, skipped };
3058
3090
  }
3059
3091
  function clientBoundRefusal(reading) {
3060
- const cite = " (SVC-L0-26).";
3092
+ const cite = ".";
3061
3093
  if (reading.admitted.size > CLIENT_FILES_MAX) {
3062
3094
  return `The zip's client/ folder holds ${reading.admitted.size} files the publish admits, more than the ${CLIENT_FILES_MAX} files one version publishes: ship fewer client files, and deploy again${cite}`;
3063
3095
  }
@@ -3160,6 +3192,8 @@ var folderBindingOf = (io2, path) => {
3160
3192
  const application = members[APPLICATION_MEMBER];
3161
3193
  return typeof application === "string" && UPLOAD_ID.test(application) ? { kind: "bound", application } : { kind: "off_form" };
3162
3194
  };
3195
+ var BINDING_LINE_HEAD = "binding: ";
3196
+ var bindingLineOf = (application) => `${BINDING_LINE_HEAD}${FOLDER_MANIFEST} gets application ${application}, so later deploy and check lines naming another application are refused`;
3163
3197
  var BOUND_LINE_HEAD = "bound: ";
3164
3198
  var boundLineOf = (application) => `${BOUND_LINE_HEAD}${FOLDER_MANIFEST} now names application ${application}; a deploy or check line naming another application is refused`;
3165
3199
  var BIND_WRITE_FAILED_LINE = `${FOLDER_MANIFEST} could not be written to bind this folder to its application, so the deploy goes on unbound, and the next deploy writes it again.`;
@@ -3566,6 +3600,7 @@ function zipFolder(root, seams = {}) {
3566
3600
  // src/turnzero_cloud_command/deploy.ts
3567
3601
  var ZIP_LINE_HEAD = "zip: ";
3568
3602
  var PREPARED_LINE_HEAD = DEPLOY_PREPARED_LINE_HEAD;
3603
+ var UPLOADING_LINE_HEAD = "uploading: ";
3569
3604
  var UPLOADED_LINE_HEAD = "uploaded: ";
3570
3605
  var STARTED_LINE_HEAD = "started: ";
3571
3606
  var WAITING_LINE_HEAD = "waiting: ";
@@ -3584,7 +3619,7 @@ var deployOptionsOf = (named, cwd, flags = /* @__PURE__ */ new Set()) => {
3584
3619
  const found = COMMAND_ENVIRONMENTS.find((name) => name === env);
3585
3620
  if (found === void 0) {
3586
3621
  return {
3587
- refusal: `${DEPLOY_OPTION.env} names the environment to deploy to, ${COMMAND_ENVIRONMENTS.join(" or ")}; a line that names none deploys to the environment the platform chooses. Nothing was started.`
3622
+ refusal: `${DEPLOY_OPTION.env} names the environment to deploy to, ${COMMAND_ENVIRONMENTS.join(" or ")}. A line that names none deploys to the environment the platform chooses. Nothing was started.`
3588
3623
  };
3589
3624
  }
3590
3625
  environment = found;
@@ -3609,9 +3644,9 @@ var DEPLOY_CREDENTIAL = Object.freeze({
3609
3644
  call: "the deploy call",
3610
3645
  mintedToken: true,
3611
3646
  piped: false,
3612
- places: `the command reads no standard input: it reads a minted token from ${MINTED_TOKEN_VARIABLE} where it is set, as a tool connected by a minted token sets it from where its token is kept, or a job with no tool from its secret store, and otherwise this computer's token for the platform's address from its credential file, which ${LOGIN_SUBCOMMAND} and ${AUTHORIZE_SUBCOMMAND} write.`
3647
+ places: NO_INPUT_PLACES
3613
3648
  });
3614
- var DEPLOY_READS = `no standard input: a minted token from ${MINTED_TOKEN_VARIABLE} where it is set, and otherwise this computer's token for the platform's address from its credential file, which ${LOGIN_SUBCOMMAND} and ${AUTHORIZE_SUBCOMMAND} write, sent only to that address; with neither, it prints the variable route first and then, where the address is admitted, the login route`;
3649
+ var DEPLOY_READS = `no standard input. It reads a minted token from ${MINTED_TOKEN_VARIABLE} where that is set. Otherwise it reads this computer's token for the platform's address from its credential file, which ${LOGIN_SUBCOMMAND} and ${AUTHORIZE_SUBCOMMAND} write, and sends it only to that address. With neither, it prints the variable route first, then the login route where the address is admitted`;
3615
3650
  var DEPLOY_AFTER_LOGIN = `Once login has printed authorized:, run this deploy line again. ${NOTHING_SENT_OR_STARTED}`;
3616
3651
  var PREPARE_ACT = "prepare";
3617
3652
  var PREPARE_AGAIN = "Nothing was started. Run the line again: it prepares a fresh upload, which replaces any upload this run prepared.";
@@ -3848,6 +3883,7 @@ async function deploy(named, io2, flags = /* @__PURE__ */ new Set()) {
3848
3883
  }
3849
3884
  io2.print(preparedLineOf(prepared));
3850
3885
  if (binding?.kind === "unbound" && binding.manifest !== null) {
3886
+ io2.print(bindingLineOf(options.application));
3851
3887
  io2.print(writeManifestMember(io2, binding.manifest, APPLICATION_MEMBER, options.application) ? boundLineOf(options.application) : BIND_WRITE_FAILED_LINE);
3852
3888
  }
3853
3889
  const { upload, grant, environment } = prepared;
@@ -3855,6 +3891,7 @@ async function deploy(named, io2, flags = /* @__PURE__ */ new Set()) {
3855
3891
  const stop = commandStopSentence(options.application, environment);
3856
3892
  const uploadNoAnswer = uploadNoAnswerSentence(options.application, environment);
3857
3893
  const address = storageFileAddress(origin, deployAreaName(options.application), uploadFileName(upload));
3894
+ io2.print(`${UPLOADING_LINE_HEAD}${zipped.zip.length} bytes as upload ${upload}`);
3858
3895
  let uploaded;
3859
3896
  try {
3860
3897
  uploaded = await writeAgain(
@@ -3984,7 +4021,7 @@ async function deploy(named, io2, flags = /* @__PURE__ */ new Set()) {
3984
4021
  io2.print(stop);
3985
4022
  return PROGRESS_EXIT_STATUS.refused;
3986
4023
  }
3987
- var DEPLOY_AFTER_OWN_ERROR = "the deploy may or may not have started: call read_status from your tool first, make the start-only retry a pending upload it answers carries, and run the line again only where it shows neither";
4024
+ var DEPLOY_AFTER_OWN_ERROR = "the deploy may or may not have started. Call read_status from your tool first, make the start-only retry a pending upload it answers carries, and run the line again only where it shows neither";
3988
4025
  var DEPLOY_ROW = Object.freeze({
3989
4026
  name: DEPLOY_SUBCOMMAND,
3990
4027
  summary: "Deploys the application folder, or a .zip file. It zips the folder, makes the preparing deploy call, uploads the zip under the upload grant that call answers, starts the deploy, and waits for it, printing each step and the outcome. It runs under this computer's token. A tool connected by a minted token, or a job with no tool, runs it under a minted token. With no credential, it sends nothing and prints the two routes to one: the minted token's variables first, then, where the address is admitted, the login route.",
@@ -3996,21 +4033,21 @@ var DEPLOY_ROW = Object.freeze({
3996
4033
  done: `the version deployed, or the deploy started where ${DEPLOY_NO_WAIT_VARIABLE} is set`,
3997
4034
  failed: "the deploy failed",
3998
4035
  unknown: "the wait stopped, or the start drew no answer: the deploy may go on, and read_status reads it",
3999
- nothing_started: "an option, credential, folder, or the folder's binding was refused, no credential was read, the platform was too old, no usable upload was answered, no zipped file names the health path, the upload or start was refused, or the upload drew no answer"
4036
+ nothing_started: "an option, credential, folder, or the folder's binding was refused, or no credential was read. Or the platform was too old, or no usable upload was answered. Or no zipped file names the health path. Or the upload or start was refused, or the upload drew no answer"
4000
4037
  },
4001
4038
  variables: [[DEPLOY_NO_WAIT_VARIABLE, "any value returns the command once the deploy has started, without waiting for it."]],
4002
4039
  note: [
4003
- `A deploy is one line, which carries no credential: run the line your tool's deploy call answers, or ${DEPLOY_SUBCOMMAND} ${DEPLOY_OPTION.application} <application id>, from the application's folder. It reads no standard input. On an authorized computer it runs under this computer's token, which ${LOGIN_SUBCOMMAND} or ${AUTHORIZE_SUBCOMMAND} keeps in the credential file for each platform address, and sends it only to the address it is kept under: ${DEPLOY_OPTION.origin} where the line names one, else the address ${ORIGIN_VARIABLE} holds, else ${DEFAULT_COMMAND_ORIGIN}.`,
4004
- `On a computer with no token for that address, or one that has expired, it sends nothing, ends 3, and prints two routes, in this order. A tool connected by a minted token, or a job with no tool, such as a CI job's, sets ${MINTED_TOKEN_VARIABLE} from where its token is kept, such as the job's secret store, never by writing the value in a line. It sets ${ORIGIN_VARIABLE} to the address that minted the token where that is not ${DEFAULT_COMMAND_ORIGIN}, then runs the deploy line again. Such a tool cannot use ${MINT_TOKEN_ACTION}, which takes a sign-in alone.`,
4005
- `Otherwise a person logs this computer in once with ${LOGIN_SUBCOMMAND}, in a terminal of their own, then runs the deploy line again; a folder within the caps of the tool's deploy_files call deploys now through deploy_files, with no login. The credential file is ${CREDENTIAL_FILE_WORDS}.`,
4040
+ `A deploy is one line, which carries no credential: run the line your tool's deploy call answers, or ${DEPLOY_SUBCOMMAND} ${DEPLOY_OPTION.application} <application id>, from the application's folder. It reads no standard input. On an authorized computer it runs under this computer's token, which ${LOGIN_SUBCOMMAND} or ${AUTHORIZE_SUBCOMMAND} keeps in the credential file for each platform address. It sends that token only to the address it is kept under: ${DEPLOY_OPTION.origin} where the line names one, else the address ${ORIGIN_VARIABLE} holds, else ${DEFAULT_COMMAND_ORIGIN}.`,
4041
+ `On a computer with no token for that address, or one that has expired, it sends nothing, ends 3, and prints two routes, in this order. A tool connected by a minted token, or a job with no tool, such as a CI job's, sets ${MINTED_TOKEN_VARIABLE} from where its token is kept, never by writing the value in a line. It sets ${ORIGIN_VARIABLE} to the address that minted the token where that is not ${DEFAULT_COMMAND_ORIGIN}, then runs the deploy line again. Such a tool cannot use ${MINT_TOKEN_ACTION}, which takes a sign-in alone.`,
4042
+ `Otherwise a person logs this computer in once with ${LOGIN_SUBCOMMAND}, in a terminal of their own, then runs the deploy line again. A folder within the caps of the tool's deploy_files call deploys now through deploy_files, with no login. The credential file is ${CREDENTIAL_FILE_WORDS}.`,
4006
4043
  `A tool sets ${MINTED_TOKEN_VARIABLE} for one line at a time and unsets it once that line ends, since the command cannot unset a variable of the shell that started it. A value a job's environment already supplies stays as it stands. A job's token is minted for the application, with an expiry. The variable's token wins over the credential file: the command makes the preparing call under that token, and sends the token in no other request.`,
4007
- `Under the variable, the command sends its token only to the address ${ORIGIN_VARIABLE} holds, or to ${DEFAULT_COMMAND_ORIGIN} where that variable is unset: under the token, ${DEPLOY_OPTION.origin} may name that address alone, and where the line names none the command addresses it. ${DEPLOY_OPTION.env} names the environment where a line names one, ${COMMAND_ENVIRONMENTS.join(" or ")}; where none is named, the platform chooses, and the command deploys to the environment the platform answers.`,
4008
- `A progress read answered 502, 503, or 504, which is often temporary, is made again, at most three more times, and an upload answered 503 credential_lookup_busy, which wrote nothing, is made again after the wait it names, at most twice.`,
4009
- `After its zip line, ${DEPLOY_SUBCOMMAND} prints the folder's top-level entries the zip holds on one line, at most ten and then the count of the rest, and ${HASH_SUBCOMMAND} ${HASH_OPTION.list} names every file; no such line prints for a .zip file.`,
4010
- `Then it prints the paths the zip left out, a warning for a .zip file at the folder's root, a warning for a file that looks like a key or a credential, and a warning for a health path that no file names, package files and documentation set aside, each on a line of its own and only where there is something to name. The health warning refuses nothing.`,
4011
- `After the preparing call, where the platform's answer names the recorded manifest's health path and says the environment serves no version, and no file of the folder's zip names that path, ${DEPLOY_SUBCOMMAND} prints the platform's own refusal, then that nothing was uploaded and nothing was started, and ends 3 with no ${PREPARED_LINE_HEAD.trimEnd()} line, as the start would refuse it. A .zip file the line names is not read for it, and the start's own refusal stands.`,
4044
+ `Under the variable, the command sends its token only to the address ${ORIGIN_VARIABLE} holds, or to ${DEFAULT_COMMAND_ORIGIN} where that variable is unset. Under the token, ${DEPLOY_OPTION.origin} may name that address alone, and where the line names none the command addresses it. ${DEPLOY_OPTION.env} names the environment where a line names one, ${COMMAND_ENVIRONMENTS.join(" or ")}. Where none is named, the platform chooses, and the command deploys to the environment the platform answers.`,
4045
+ `A progress read answered 502, 503, or 504, which is often temporary, is made again, at most three more times. An upload answered 503 credential_lookup_busy, which wrote nothing, is made again after the wait it names, at most twice.`,
4046
+ `After its zip line, ${DEPLOY_SUBCOMMAND} prints the folder's top-level entries the zip holds on one line, at most ten and then the count of the rest. ${HASH_SUBCOMMAND} ${HASH_OPTION.list} names every file. No such line prints for a .zip file.`,
4047
+ `Then it prints the paths the zip left out, a warning for a .zip file at the folder's root, and a warning for a file that looks like a key or a credential. It warns of a health path that no file names, package files and documentation set aside. Each prints on a line of its own, only where there is something to name. The health warning refuses nothing.`,
4048
+ `After the preparing call, the platform's answer may name the recorded manifest's health path and say the environment serves no version. Where no file of the folder's zip names that path, ${DEPLOY_SUBCOMMAND} prints the platform's own refusal, then that nothing was uploaded and nothing was started. It ends 3 with no ${PREPARED_LINE_HEAD.trimEnd()} line, as the start would refuse it. A .zip file the line names is not read for it, and the start's own refusal stands.`,
4012
4049
  `Before its zip, ${DEPLOY_SUBCOMMAND} reads the folder's manifest.json. Where its application member names another application than ${DEPLOY_OPTION.application}, or is not an application id, the deploy ends 3 before anything is zipped or sent. To deploy the folder to another application on purpose, the account's owner changes or removes that member.`,
4013
- `Where the manifest holds no application member, ${DEPLOY_SUBCOMMAND} writes ${DEPLOY_OPTION.application}'s id into it after the ${PREPARED_LINE_HEAD.trimEnd()} line and prints a ${BOUND_LINE_HEAD.trimEnd()} line, so later deploy and check lines naming another application are refused. A write that fails prints one line and stops nothing. A .zip file the line names is not read for it.`
4050
+ `Where the manifest holds no application member, ${DEPLOY_SUBCOMMAND} prints a ${BINDING_LINE_HEAD.trimEnd()} line after the ${PREPARED_LINE_HEAD.trimEnd()} line, then writes ${DEPLOY_OPTION.application}'s id into it and prints a ${BOUND_LINE_HEAD.trimEnd()} line. Later deploy and check lines naming another application are then refused. A write that fails prints one line and stops nothing. A .zip file the line names is not read for it.`
4014
4051
  ],
4015
4052
  afterOwnError: DEPLOY_AFTER_OWN_ERROR,
4016
4053
  run: (call, io2) => deploy(call.named, io2, call.flags)
@@ -4023,6 +4060,8 @@ var BINDING_NOTHING_CHECKED = "Nothing further was read, and nothing was sent or
4023
4060
  var REFUSED_LINE_HEAD = "refused: ";
4024
4061
  var MANIFEST_LINE_HEAD = "manifest: ";
4025
4062
  var CHECKED_LINE_HEAD = "checked: ";
4063
+ var CHECKING_LINE_HEAD = "checking: ";
4064
+ var checkingLineOf = (application) => `${CHECKING_LINE_HEAD}application ${application} on the platform, then the zip.`;
4026
4065
  var CHECK_ACT = "check";
4027
4066
  var CHECK_CALL_BOUND_SECONDS = 60;
4028
4067
  var CHECK_NO_ANSWER = "The check call drew no answer.";
@@ -4074,9 +4113,9 @@ var CHECK_CREDENTIAL = Object.freeze({
4074
4113
  call: `the ${CHECK_ACTION} call`,
4075
4114
  mintedToken: true,
4076
4115
  piped: false,
4077
- places: `the command reads no standard input: it reads a minted token from ${MINTED_TOKEN_VARIABLE} where it is set, as a tool connected by a minted token sets it from where its token is kept, or a job with no tool from its secret store, and otherwise this computer's token for the platform's address from its credential file, which ${LOGIN_SUBCOMMAND} and ${AUTHORIZE_SUBCOMMAND} write.`
4116
+ places: NO_INPUT_PLACES
4078
4117
  });
4079
- var CHECK_READS = `no standard input: a minted token from ${MINTED_TOKEN_VARIABLE} where it is set, and otherwise this computer's token for the platform's address from its credential file, which ${LOGIN_SUBCOMMAND} and ${AUTHORIZE_SUBCOMMAND} write, sent only to that address; with neither, it prints the variable route first and then, where the address is admitted, the login route`;
4118
+ var CHECK_READS = `no standard input. It reads a minted token from ${MINTED_TOKEN_VARIABLE} where that is set. Otherwise it reads this computer's token for the platform's address from its credential file, which ${LOGIN_SUBCOMMAND} and ${AUTHORIZE_SUBCOMMAND} write, and sends it only to that address. With neither, it prints the variable route first, then the login route where the address is admitted`;
4080
4119
  var checkAnswerOf = (answer) => {
4081
4120
  const { refusals, first_deploy: firstDeploy, recorded_health_path: recordedHealthPath } = answer;
4082
4121
  if (!Array.isArray(refusals) || typeof firstDeploy !== "boolean" || typeof recordedHealthPath !== "string") return null;
@@ -4226,6 +4265,7 @@ async function check(named, io2) {
4226
4265
  return COMMAND_STATUS.nothing_started;
4227
4266
  }
4228
4267
  io2.print(zipped.line);
4268
+ io2.print(checkingLineOf(options.application));
4229
4269
  const older = await planeWireRefusal(io2, origin);
4230
4270
  if (older !== null) {
4231
4271
  io2.print(older);
@@ -4253,11 +4293,11 @@ var CHECK_ROW = Object.freeze({
4253
4293
  statuses: {
4254
4294
  done: "none of the checks would refuse a deploy now",
4255
4295
  failed: "a deploy would be refused now, the refused: lines naming each refusal",
4256
- nothing_started: "nothing was checked: an option, credential, folder, or the folder's binding was refused, no credential was read and the two routes to one were printed, the platform was too old, or the check call was refused, drew no answer, was redirected, or failed"
4296
+ nothing_started: "nothing was checked. An option, credential, folder, or the folder's binding was refused, or no credential was read and the two routes to one were printed. Or the platform was too old. Or the check call was refused, drew no answer, was redirected, or failed"
4257
4297
  },
4258
4298
  note: [
4259
4299
  `A check is one line, which carries no credential: run the line your tool's ${CHECK_ACTION} call answers, or ${CHECK_SUBCOMMAND} ${CHECK_OPTION.application} <application id>, from the application's folder, before a first deploy and after each fix. It reads its credential and the platform's address as ${DEPLOY_SUBCOMMAND} does, builds the zip ${DEPLOY_SUBCOMMAND} builds, and sends the platform the application alone, no byte of the zip and no hash. It uploads nothing and starts nothing.`,
4260
- `After its zip line, ${CHECK_SUBCOMMAND} prints the further lines ${DEPLOY_SUBCOMMAND} prints, leaving out the health warning where the platform says the deploy would be a first one, since a refused: line then reads the recorded health path. Then it prints one refused: line for each refusal the platform answered for the application's state, then one for each refusal of the zip by the deploy's own checks, a line naming submit_manifest where the zip's manifest.json names another health path, and a last checked: line counting the refusals.`,
4300
+ `After its zip line and a checking: line, ${CHECK_SUBCOMMAND} prints the further lines ${DEPLOY_SUBCOMMAND} prints. It leaves out the health warning where the platform says the deploy would be a first one, since a refused: line then reads the recorded health path. Then it prints one refused: line for each refusal the platform answered for the application's state, then one for each refusal of the zip by the deploy's own checks. A line names submit_manifest where the zip's manifest.json names another health path, and a last checked: line counts the refusals.`,
4261
4301
  `Before its zip, ${CHECK_SUBCOMMAND} reads the folder's manifest.json as ${DEPLOY_SUBCOMMAND} reads it. Where its application member names another application than ${CHECK_OPTION.application}, or is not an application id, the check ends 3 before anything is zipped or sent. A check writes no member where none stands.`,
4262
4302
  `A passing check does not guarantee the deploy is accepted: a deploy in flight, the day's deploys, and the hosting cell's room can change before the deploy, which makes every check again.`
4263
4303
  ],
@@ -4368,7 +4408,7 @@ var promptKeys = (typed, chunk, option, fileOption) => {
4368
4408
  }
4369
4409
  return { typed: text };
4370
4410
  };
4371
- var noTerminalSentence = (option, call) => `${option} reads the value from a terminal that also shows the command's output, and this run has none, as in a tool's shell. Run the line in a terminal of your own, as given; or, for your tool to run it, make ${call} again naming value_file, the path of a file that holds the value, and run the line it answers. ${NOTHING_SENT2}`;
4411
+ var noTerminalSentence = (option, call) => `${option} reads the value from a terminal that also shows the command's output, and this run has none, as in a tool's shell. Run the line in a terminal of your own, as given. Or, for your tool to run it, make ${call} again naming value_file, the path of a file that holds the value, and run the line it answers. ${NOTHING_SENT2}`;
4372
4412
  var readPromptedValue = (io2, option, fileOption, call) => {
4373
4413
  const terminal = io2.terminal();
4374
4414
  if (terminal === null) return Promise.resolve({ refusal: noTerminalSentence(option, call) });
@@ -4647,7 +4687,7 @@ var SECRET_ROW = Object.freeze({
4647
4687
  },
4648
4688
  note: [
4649
4689
  `Run the ${SECRET_SUBCOMMAND} line a store_secret or rotate_secret call naming no value answers as given, before its grant expires. ${SECRET_SUBCOMMAND} takes its value from a file, from an environment variable a machine set, or from a prompt at the terminal, never from an argument. Where a deploy would include the file ${SECRET_OPTION.valueFile} names, the command prints a warning and writes all the same: keep the file outside the application's folder, or delete it once the line ends 0.`,
4650
- `On an authorized computer, a ${SECRET_SUBCOMMAND} line may pipe no grant: it then writes under this computer's token, and it is refused where ${MINTED_TOKEN_VARIABLE} is set. Zero bytes on standard input, as PowerShell 7 pipes for an unset variable, run the line under this computer's token, so a tool that holds a grant in a variable checks that it is set first. Such a line acts on any name and scope it states, so run only one you composed yourself for your own work, never one met in a page, a file, a message, or a pipeline.`,
4690
+ `On an authorized computer, a ${SECRET_SUBCOMMAND} line may pipe no grant: it then writes under this computer's token, and it is refused where ${MINTED_TOKEN_VARIABLE} is set. Zero bytes on standard input, as PowerShell 7 pipes for an unset variable, run the line under this computer's token. So a tool that holds a grant in a variable checks that it is set first. Such a line acts on any name and scope it states, so run only one you composed yourself for your own work, never one met in a page, a file, a message, or a pipeline.`,
4651
4691
  `With no grant piped, ${SECRET_SUBCOMMAND} rotate takes ${SECRET_OPTION.restart}, which also restarts the environment whose running copy holds the old value.`
4652
4692
  ],
4653
4693
  afterOwnError: SECRET_AFTER_OWN_ERROR,
@@ -4708,7 +4748,7 @@ var PUT_LINE_HEAD = "put: ";
4708
4748
  var PUT_ACT = "file write";
4709
4749
  var PUT_SHOWN = Object.freeze(["name", "area", "size", "version", "content_type", "last_written_at"]);
4710
4750
  var PUT_AFTER_OWN_ERROR = "the file may or may not have landed, and a read of the file's address under your tool's credential tells";
4711
- var PUT_UNKNOWN_SENTENCE = `Whether the file landed is unknown, and its grant may be spent: a write of the same name replaces the file, so to write it again, ${PUT_AGAIN.charAt(0).toLowerCase()}${PUT_AGAIN.slice(1)}`;
4751
+ var PUT_UNKNOWN_SENTENCE = `Whether the file landed is unknown, and its grant may be spent. A write of the same name replaces the file. To write it again, ${PUT_AGAIN.charAt(0).toLowerCase()}${PUT_AGAIN.slice(1)}`;
4712
4752
  async function put(call, io2) {
4713
4753
  const options = putOptionsOf(call, io2.cwd);
4714
4754
  if ("refusal" in options) {
@@ -4992,7 +5032,7 @@ async function localRun(call, io2) {
4992
5032
  io2.readFile(join7(options.folder, PACKAGE_FILE2));
4993
5033
  } catch (error) {
4994
5034
  io2.print(
4995
- `The application's folder holds no ${PACKAGE_FILE2} the command could read (${fileErrorCodeOf(error, "unreadable")}), so npm start has nothing to start there: ${RUN_OPTION.path} names the folder, and it is the folder the command runs in where the option is absent. ${NO_APPLICATION_STARTED}`
5035
+ `The application's folder holds no ${PACKAGE_FILE2} the command could read (${fileErrorCodeOf(error, "unreadable")}), so npm start has nothing to start there. ${RUN_OPTION.path} names the folder, and it is the folder the command runs in where the option is absent. ${NO_APPLICATION_STARTED}`
4996
5036
  );
4997
5037
  return COMMAND_STATUS.nothing_started;
4998
5038
  }
@@ -5037,8 +5077,8 @@ var RUN_ROW = Object.freeze({
5037
5077
  note: [
5038
5078
  `${RUN_BACKGROUND_SENTENCE} ${RUN_SUBCOMMAND} ends with the application's own status, whatever it is, so a status under ${RUN_SUBCOMMAND} may be the application's and not the command's. Where no application was started, the command's own lines say so, so a 3 with no such line is the application's own.`,
5039
5079
  `While the application runs, an interrupt does not end the command before the application. On macOS and Linux it is passed on where standard input is no terminal, and on Windows the application runs on the command's console, which hands it the interrupt itself.`,
5040
- `Where the line was started with npx.cmd, cmd asks Terminate batch job (Y/N)? once after the command ends, and either answer returns the prompt, N keeping the command's status and Y ending with cmd's own; the command's last line after an interrupted run on Windows says so, on a line of its own. A shell whose npx is no batch file, Git Bash or a PowerShell that runs scripts, asks nothing. After an interrupt on Windows, the status is npm's, or cmd's where the command had to start npm through cmd, and may not be the application's.`,
5041
- `${RUN_SUBCOMMAND} leaves ${COMMAND_CREDENTIAL_VARIABLES.join(" and ")} out of what the application receives. It replaces a value in the output only where the application prints it as it received it, or a connection string's password with its percent escapes read, and it leaves a value under eight characters as it is.`
5080
+ `Where the line was started with npx.cmd, cmd asks Terminate batch job (Y/N)? once after the command ends. Either answer returns the prompt, N keeping the command's status and Y ending with cmd's own. The command's last line after an interrupted run on Windows says so, on a line of its own. A shell whose npx is no batch file, Git Bash or a PowerShell that runs scripts, asks nothing. After an interrupt on Windows, the status is npm's, or cmd's where the command had to start npm through cmd, and may not be the application's.`,
5081
+ `${RUN_SUBCOMMAND} leaves ${COMMAND_CREDENTIAL_VARIABLES.join(" and ")} out of what the application receives. It replaces a value in the output only where the application prints it as it received it, or a connection string's password with its percent escapes read. It leaves a value under eight characters as it is.`
5042
5082
  ],
5043
5083
  afterOwnError: "the application may or may not have been started",
5044
5084
  run: localRun
@@ -5072,9 +5112,9 @@ var LIBRARY_CREDENTIAL = Object.freeze({
5072
5112
  call: `the ${LIBRARY_READ_ACTION} call`,
5073
5113
  mintedToken: true,
5074
5114
  piped: false,
5075
- places: `the command reads no standard input: it reads a minted token from ${MINTED_TOKEN_VARIABLE} where it is set, as a tool connected by a minted token sets it from where its token is kept, or a job with no tool from its secret store, and otherwise this computer's token for the platform's address from its credential file, which ${LOGIN_SUBCOMMAND} and ${AUTHORIZE_SUBCOMMAND} write.`
5115
+ places: NO_INPUT_PLACES
5076
5116
  });
5077
- var LIBRARY_READS = `no standard input: a minted token from ${MINTED_TOKEN_VARIABLE} where it is set, and otherwise this computer's token for the platform's address from its credential file, which ${LOGIN_SUBCOMMAND} and ${AUTHORIZE_SUBCOMMAND} write, sent only to that address; with neither, it prints the variable route first and then, where the address is admitted, the login route`;
5117
+ var LIBRARY_READS = `no standard input. It reads a minted token from ${MINTED_TOKEN_VARIABLE} where that is set. Otherwise it reads this computer's token for the platform's address from its credential file, which ${LOGIN_SUBCOMMAND} and ${AUTHORIZE_SUBCOMMAND} write, and sends it only to that address. With neither, it prints the variable route first, then the login route where the address is admitted`;
5078
5118
  var TAKE_AFTER_LOGIN = `Once ${LOGIN_SUBCOMMAND} has printed authorized:, run this take line again. ${NOTHING_WRITTEN2}`;
5079
5119
  var takeRedirectedLine = (status) => `${LIBRARY_READ_ACTION} was answered ${status >= 100 ? `${answeredHow(status)}, a redirect` : answeredHow(status)}, which the command never follows, so the credential was sent to no second address. ${NOTHING_WRITTEN2}`;
5080
5120
  async function readTakeCredential(io2, named, afterLogin, why) {
@@ -5087,7 +5127,7 @@ async function readTakeCredential(io2, named, afterLogin, why) {
5087
5127
  const unwritable = loginRouteRefusalOf(io2, NOTHING_WRITTEN2);
5088
5128
  if (unwritable !== null) return { lines: [...head, VARIABLE_ROUTE_SENTENCES, unwritable] };
5089
5129
  const route = loginRouteLines(io2, origin.origin, false);
5090
- return { lines: [...head, VARIABLE_ROUTE_SENTENCES, ...route, afterLogin] };
5130
+ return { lines: [...head, VARIABLE_ROUTE_SENTENCES, authorizeRouteSentence(origin.origin), ...route, afterLogin] };
5091
5131
  }
5092
5132
  if ("refusal" in read2) return { lines: [read2.refusal] };
5093
5133
  io2.hide(read2.credential, REDACTED_TOKEN);
@@ -5339,12 +5379,28 @@ var openingCharacterClauseOf = (text) => {
5339
5379
  const control = first < 32 && first !== 9 && first !== 10 && first !== 13 || first >= 127 && first <= 159;
5340
5380
  return control ? `: the file opens with ${point}, a control character` : "";
5341
5381
  };
5382
+ var APPLICATION_IN_APP_LINE = "No package.json stands at the project's root or in app/, so the application goes in app/.";
5383
+ var ROOT_SOURCE_FILE = /\.(?:[cm]?[jt]s|[jt]sx)$/;
5384
+ var startedAtRootOf = (io2, root) => (io2.listFolder(root) ?? []).flatMap((name) => {
5385
+ const standing = io2.stat(join8(root, name));
5386
+ if (standing === null) return [];
5387
+ if (name === "package.json") return standing.folder ? [] : [name];
5388
+ if (name === "src") return standing.folder ? ["src/"] : [];
5389
+ return !standing.folder && ROOT_SOURCE_FILE.test(name) ? [name] : [];
5390
+ }).sort();
5391
+ var startedWordsOf = (names) => {
5392
+ const shown2 = names.length > 3 ? [...names.slice(0, 3).map(shownName), `${names.length - 3} more`] : names.map(shownName);
5393
+ return shown2.length < 3 ? shown2.join(" and ") : `${shown2.slice(0, -1).join(", ")}, and ${shown2[shown2.length - 1]}`;
5394
+ };
5395
+ var startedRootTakeRefusal = (names) => `The project's root holds ${startedWordsOf(names)} and no package.json, so the take would start the application in app/ beside them. To keep the application at the root, add its package.json there. To start it in app/, move those files into app/. Then run this line again. ${NOTHING_WRITTEN2}`;
5342
5396
  var applicationFolderOf = (io2, root) => [join8(root, "app"), root].find((folder) => io2.stat(join8(folder, "package.json"))?.folder === false) ?? null;
5343
5397
  var copyPlanOf = (io2, root, library, name) => {
5344
5398
  const shown2 = shownFrom(root);
5345
5399
  if (name.includes("/")) return { refusal: `The entry ${LIBRARY_OPTION.entry} names carries compiled modules under a name that holds a slash, which an npm package cannot take. ${NOTHING_WRITTEN2}` };
5346
5400
  const application = applicationFolderOf(io2, root);
5347
5401
  if (application === null) {
5402
+ const started = startedAtRootOf(io2, root);
5403
+ if (started.length > 0) return { refusal: startedRootTakeRefusal(started) };
5348
5404
  const app = join8(root, MADE_FOLDER);
5349
5405
  const standing = io2.stat(app);
5350
5406
  if (standing !== null && !standing.folder || danglingLinkAt(io2, root, MADE_FOLDER)) {
@@ -5508,12 +5564,12 @@ var committedFilesOf = (copied, written) => {
5508
5564
  if (files.length === 1) return files[0];
5509
5565
  return `${files.slice(0, -1).join(", ")}${files.length > 2 ? "," : ""} and ${files[files.length - 1]}`;
5510
5566
  };
5511
- var COPY_PACKAGES_CLAUSE = "copy the packages line into the application manifest's packages member at each submission; ";
5512
- var KEEP_PACKAGES_CLAUSE = "the application manifest was written whole, so read it again before patching it, carry its packages member over in any later rewrite, and call submit_manifest with it before the next deploy; ";
5513
- var MADE_MANIFEST_CLAUSE = "the application manifest was made with no services and a public audience, so declare the services and the audience the application uses in it before submit_manifest; ";
5567
+ var COPY_PACKAGES_CLAUSE = "Copy the packages line into the application manifest's packages member at each submission. ";
5568
+ var KEEP_PACKAGES_CLAUSE = "The application manifest was written whole, so read it again before patching it, and carry its packages member over in any later rewrite. Call submit_manifest with it before the next deploy. ";
5569
+ var MADE_MANIFEST_CLAUSE = "The application manifest was made with no services and a public audience. Declare the services and the audience the application uses in it before submit_manifest. ";
5514
5570
  var installFailedSentence = (folder) => `npm install in ${folder} did not finish: the entry, its row, and the copy are written. Run npm install there again; running this line again takes the entry again whole.`;
5515
5571
  var LIBRARY_AFTER_OWN_ERROR = "the entry's folder, its manifest row, or the application's copy may stand in part, and running the line again replaces each whole";
5516
- async function readTake(io2, options, userAgent, bearer, planOf, planeChecked = false) {
5572
+ async function readTake(io2, options, userAgent, bearer, planOf, planeChecked = false, say = () => void 0) {
5517
5573
  const refuse = (...lines) => ({ lines });
5518
5574
  const found = libraryFolderOf(io2, options.root);
5519
5575
  if ("refusal" in found) return refuse(found.refusal);
@@ -5553,6 +5609,7 @@ async function readTake(io2, options, userAgent, bearer, planOf, planeChecked =
5553
5609
  if (besideCopy !== null) return refuse(besideCopy);
5554
5610
  const staged = stageRefusalOf(io2, join8(library, STAGE), "the library folder") ?? (plan !== null ? stageRefusalOf(io2, `${plan.copy}${STAGE}`, "the application's copy") : null);
5555
5611
  if (staged !== null) return refuse(staged);
5612
+ say(readingLineOf(entry.name, entry.version, entry.files.length));
5556
5613
  const bytes = /* @__PURE__ */ new Map();
5557
5614
  for (const file of entry.files) {
5558
5615
  const read2 = await fileBytesOf(io2, options.origin, bearer, userAgent, entry.name, file);
@@ -5565,6 +5622,8 @@ async function readTake(io2, options, userAgent, bearer, planOf, planeChecked =
5565
5622
  const packages = packagesOf(manifestTextOf(manifest.rows, { name: entry.name, version: entry.version, closure_hash: entry.closure_hash, source_commit: entry.source_commit, fetched_at: "" }));
5566
5623
  return { entry, library, fresh: found.fresh, entryFolder, rows: manifest.rows, manifestStood: manifest.stood, compiled, plan: planned, bytes, packages };
5567
5624
  }
5625
+ var READING_LINE_HEAD = "reading: ";
5626
+ var readingLineOf = (name, version, files) => `${READING_LINE_HEAD}${name} ${version === null ? "with no version" : shownWhole(version)}, ${files} ${files === 1 ? "file" : "files"} from the library to check.`;
5568
5627
  function writeTake(io2, root, { entry, library, entryFolder, rows, manifestStood, compiled, plan, bytes }) {
5569
5628
  const shown2 = shownFrom(root);
5570
5629
  io2.makeFolder(library);
@@ -5644,7 +5703,7 @@ async function installTake(io2, root, plan, manifestText, application) {
5644
5703
  io2.print(`${packagesLineOf(packagesOf(manifestText))} ${packagesWhereOf(root, application)}`);
5645
5704
  if (!("written" in application) && application.unwritten === "write_failed") status = COMMAND_STATUS.failed;
5646
5705
  io2.print(
5647
- `next: commit ${committedFilesOf(plan !== null, "written" in application)}; ${"written" in application ? `${application.made === true ? MADE_MANIFEST_CLAUSE : ""}${KEEP_PACKAGES_CLAUSE}` : COPY_PACKAGES_CLAUSE}and, where the project holds the registrar, pin the version in its instance file and run validate with kind library.`
5706
+ `next: commit ${committedFilesOf(plan !== null, "written" in application)}. ${"written" in application ? `${application.made === true ? MADE_MANIFEST_CLAUSE : ""}${KEEP_PACKAGES_CLAUSE}` : COPY_PACKAGES_CLAUSE}Where the project holds the registrar, pin the version in its instance file and run validate with kind library.`
5648
5707
  );
5649
5708
  printAfterInterrupt(io2, afterInterrupt);
5650
5709
  return status;
@@ -5665,10 +5724,11 @@ async function libraryTake(call, io2) {
5665
5724
  if (fromApplication !== null) return refuse(fromApplication);
5666
5725
  const held = await readTakeCredential(io2, call.named[LIBRARY_OPTION.origin], TAKE_AFTER_LOGIN);
5667
5726
  if ("lines" in held) return refuse(...held.lines);
5668
- const checked = await readTake(io2, { ...options, origin: held.origin }, agent.userAgent, held.bearer, (library, name) => copyPlanOf(io2, options.root, library, name));
5727
+ const checked = await readTake(io2, { ...options, origin: held.origin }, agent.userAgent, held.bearer, (library, name) => copyPlanOf(io2, options.root, library, name), false, (line) => io2.print(line));
5669
5728
  if ("lines" in checked) return refuse(...checked.lines);
5670
5729
  const application = applicationManifestOf(io2, options.root, checked.library, checked.plan?.application ?? applicationFolderOf(io2, options.root));
5671
5730
  if ("refusal" in application) return refuse(application.refusal);
5731
+ if (checked.plan?.made !== void 0) io2.print(APPLICATION_IN_APP_LINE);
5672
5732
  const manifestText = writeTake(io2, options.root, checked);
5673
5733
  const written = writeApplicationManifest(io2, application, packagesOf(manifestText));
5674
5734
  return installTake(io2, options.root, checked.plan, manifestText, written);
@@ -5686,7 +5746,10 @@ var LIBRARY_ROW = Object.freeze({
5686
5746
  failed: "the entry, its row, and the copy written, and npm install failed or the application manifest's packages was not written",
5687
5747
  nothing_started: "nothing was written"
5688
5748
  },
5689
- note: [`Run the ${LIBRARY_SUBCOMMAND} line at the project's root: the folder that holds system/ or system.json beside app/, or, on a first take, the folder a new system/ is made in. Where that folder holds neither and the folder above it holds one, the take is refused, and its sentence names both ways on. It writes nothing until every file is checked.`],
5749
+ note: [
5750
+ `Run the ${LIBRARY_SUBCOMMAND} line at the project's root: the folder that holds system/ or system.json beside app/, or, on a first take, the folder a new system/ is made in. Where that folder holds neither and the folder above it holds one, the take is refused, and its sentence names both ways on. It writes nothing until every file is checked.`,
5751
+ `For an entry with compiled modules, the application's folder is app/ where it holds package.json, else the project's root where it does. Where neither stands, the take says so first, then makes app/package.json and places the copy in app/. It refuses, writing nothing, where the root holds no package.json but src/ or a source file such as server.mjs, since app/ would then stand beside that code.`
5752
+ ],
5690
5753
  afterOwnError: LIBRARY_AFTER_OWN_ERROR,
5691
5754
  run: libraryTake
5692
5755
  });
@@ -5759,7 +5822,7 @@ var stateOnlyAnswer = (origin) => ({ status: 204, headers: answerHeaders(origin,
5759
5822
  var outcomeAnswer = (origin, authorized) => ({
5760
5823
  status: 200,
5761
5824
  headers: answerHeaders(origin, true),
5762
- body: authorized ? browserPageOf("This computer is logged in", `The turnzero command on this computer is logged in at ${origin}. You can close this tab.`) : browserPageOf("The login did not complete", "The turnzero command on this computer did not complete the login; its terminal says why and what to run next. You can close this tab.")
5825
+ body: authorized ? browserPageOf("This computer is logged in", `The turnzero command on this computer is logged in at ${origin}. Return to your AI tool and continue the setup or deployment you started. You can close this tab.`) : browserPageOf("The login did not complete", "The turnzero command on this computer did not complete the login; its terminal says why and what to run next. You can close this tab.")
5763
5826
  });
5764
5827
  var wrongStateAnswer = (origin) => ({
5765
5828
  status: 400,
@@ -5912,7 +5975,7 @@ async function login(call, io2) {
5912
5975
  io2.print(notCodeSentence(again));
5913
5976
  return COMMAND_STATUS.nothing_started;
5914
5977
  }
5915
- const status = await completeAct(io2, origin.origin, "authorized computer", arrival.code, agent.userAgent, io2.print, () => void 0, again);
5978
+ const status = await completeAct(io2, origin.origin, "authorized computer", { code: arrival.code }, agent.userAgent, io2.print, () => void 0, again);
5916
5979
  outcome(status === COMMAND_STATUS.done);
5917
5980
  return status;
5918
5981
  } finally {
@@ -5937,19 +6000,19 @@ var LOGIN_OPTIONS = Object.freeze([
5937
6000
  description: "Opens no browser and binds no port: open the printed address in a browser on any computer, approve, and paste the code the page shows."
5938
6001
  }
5939
6002
  ]);
5940
- var LOGIN_AFTER_OWN_ERROR = "the login may not have completed; where a token was minted, list_tokens from your tool shows it by its label, and revoke_token ends it; run login again to log this computer in";
6003
+ var LOGIN_AFTER_OWN_ERROR = "the login may not have completed. Where a token was minted, list_tokens from your tool shows it by its label, and revoke_token ends it. Run login again to log this computer in";
5941
6004
  var LOGIN_ROW = Object.freeze({
5942
6005
  name: LOGIN_SUBCOMMAND,
5943
6006
  summary: `Logs this computer in at the platform's address. It opens the platform's computer login page (${COMPUTER_LOGIN_PATH}) in your default browser, where you approve the login under your sign-in. It keeps the token the platform mints in this computer's credential file. It then reads the account the token acts as, and prints authorized: with the address, the account's sign-in address (or its id where it has none), the token's label, and its expiry. Where the browser cannot answer, it asks for the code the page shows. It prints no token, code, or verifier.`,
5944
6007
  example: LOGIN_SUBCOMMAND,
5945
6008
  options: LOGIN_OPTIONS,
5946
6009
  credential: null,
5947
- reads: "nothing from standard input; with the browser it waits for the page to answer on a port of this computer, and with --no-browser it reads the code the page shows from the terminal, hidden; once the token is kept, it reads the account through read_account under it",
6010
+ reads: "nothing from standard input. With the browser, it waits for the page to answer on a port of this computer. With --no-browser, it reads the code the page shows from the terminal, hidden. Once the token is kept, it reads the account through read_account under it",
5948
6011
  statuses: {
5949
6012
  done: "this computer logged in",
5950
6013
  failed: "a token was minted and not kept, or the token this computer held before was not revoked: the printed lines name revoke_token",
5951
6014
  unknown: "the exchange drew no answer, or an answer that is not a refusal: list_tokens shows whether a token was minted",
5952
- nothing_started: "nothing was minted: an option or the credential file was refused, no code arrived in time or could arrive, the prompt was stopped or given what is not a token code, the platform was too old, or the exchange was refused"
6015
+ nothing_started: "nothing was minted. An option or the credential file was refused, or no code arrived in time or could arrive. Or the prompt was stopped, or given what is not a token code. Or the platform was too old, or the exchange was refused"
5953
6016
  },
5954
6017
  variables: [[ORIGIN_VARIABLE, AUTHORIZATION_ORIGIN_VARIABLE_LINE]],
5955
6018
  note: [
@@ -5970,7 +6033,7 @@ var LOGOUT_OPTIONS = Object.freeze([
5970
6033
  }
5971
6034
  ]);
5972
6035
  var NOTHING_REMOVED = "Nothing was sent and nothing was removed.";
5973
- var LOGOUT_AFTER_OWN_ERROR = "the token may or may not have been revoked, and this computer's entries for the origin may stand in the credential file: list_tokens from your tool shows whether the token stands, and revoke_token ends it";
6036
+ var LOGOUT_AFTER_OWN_ERROR = "the token may or may not have been revoked, and this computer's entries for the origin may stand in the credential file. list_tokens from your tool shows whether the token stands, and revoke_token ends it";
5974
6037
  var loggedOutLineOf = (origin, ended) => `${LOGGED_OUT_LINE_HEAD}${origin}, ${ended === null ? "the request pending there removed; no token was kept for it" : ended.how === "revoked" ? `token ${ended.id} revoked and removed from this computer` : ended.how === "ended" ? `token ${ended.id} removed from this computer, which had already ended` : `token ${ended.id} removed from this computer and not revoked`}`;
5975
6038
  async function logout(call, io2) {
5976
6039
  const origin = entryOriginOf(io2.env, call.named[DEPLOY_OPTION.origin], NOTHING_REMOVED);
@@ -6071,7 +6134,7 @@ var whoamiLinesOf = (origin, account, entry) => [
6071
6134
  `${WHOAMI_LINE_HEADS.token}label ${entry.label !== null ? JSON.stringify(entry.label) : "none"}, expiring ${entry.expires_at !== null ? `at ${entry.expires_at}` : "never"}`
6072
6135
  ];
6073
6136
  var noComputerTokenSentence = (origin, expiredAt) => expiredAt === null ? `This computer's credential file holds no token for ${origin}, so nothing was sent.` : `This computer's token for ${origin} in its credential file expired at ${expiredAt}, so nothing was sent.`;
6074
- var noLoginRoutesSentence = (origin) => `Your AI coding tool's own sign-in is not this computer's credential. With no login, deploy_files deploys a folder within its caps, ${AUTHORIZE_SUBCOMMAND}${originWordsOf(origin)} run with nothing piped prints the ${MINT_TOKEN_ACTION} call a signed-in tool makes to authorize this computer, and ${PROVISION_SUBCOMMAND}${originWordsOf(origin)} run so prints the call that answers its line.`;
6137
+ var noLoginRoutesSentence = (origin) => `Your AI coding tool's own sign-in is not this computer's credential. With no login, deploy_files deploys a folder within its caps. ${authorizeRouteSentence(origin)} ${PROVISION_SUBCOMMAND}${originWordsOf(origin)} run so prints the call that answers its line.`;
6075
6138
  var whoamiAfterLoginSentence = (whoami2) => `Once login has printed authorized:, run ${whoami2} again.`;
6076
6139
  async function whoami(call, io2) {
6077
6140
  const origin = entryOriginOf(io2.env, call.named[DEPLOY_OPTION.origin], NOTHING_SENT_OR_READ);
@@ -6135,7 +6198,7 @@ var WHOAMI_ROW = Object.freeze({
6135
6198
  done: "the account was read",
6136
6199
  failed: "the platform refused the read, where it no longer accepts the token among other causes: the printed lines name login",
6137
6200
  unknown: "the read drew no answer, or an answer that is not a refusal",
6138
- nothing_started: "nothing was read: an option or the credential file was refused, the platform was too old, or no live token stands for the address, and the printed lines name the ways on with no login, then the login route"
6201
+ nothing_started: "nothing was read. An option or the credential file was refused, or the platform was too old. Or no live token stands for the address, and the printed lines name the ways on with no login, then the login route"
6139
6202
  },
6140
6203
  variables: [[ORIGIN_VARIABLE, `the platform's address whose token is read where the line names no ${DEPLOY_OPTION.origin}.`]],
6141
6204
  note: [`${WHOAMI_SUBCOMMAND} reads which account a login or an authorize on this computer kept a token for, so you can tell it from your tool's own connection. The credential file is ${CREDENTIAL_FILE_WORDS}.`],
@@ -6333,21 +6396,21 @@ var PROVISION_CREDENTIAL = Object.freeze({
6333
6396
  call: "the submit_manifest call naming local_run",
6334
6397
  mintedToken: true,
6335
6398
  piped: false,
6336
- places: `the command reads no standard input: it reads a minted token from ${MINTED_TOKEN_VARIABLE} where it is set, as a tool connected by a minted token sets it from where its token is kept, or a job with no tool from its secret store, and otherwise this computer's token for the platform's address from its credential file, which ${LOGIN_SUBCOMMAND} and ${AUTHORIZE_SUBCOMMAND} write.`,
6399
+ places: NO_INPUT_PLACES,
6337
6400
  claim: `this computer's pending verifier, under ${PROVISION_CLAIM_FLAG}`
6338
6401
  });
6339
- var PROVISION_READS = `no standard input: a minted token from ${MINTED_TOKEN_VARIABLE} where it is set, and otherwise this computer's token for the platform's address from its credential file, which ${LOGIN_SUBCOMMAND} and ${AUTHORIZE_SUBCOMMAND} write, sent only to that address; else ${PROVISION_CREDENTIAL.claim}; with none, it keeps a verifier and prints the challenge and the submit_manifest call naming local_run and ${CODE_CHALLENGE_MEMBER}`;
6402
+ var PROVISION_READS = `no standard input. It reads a minted token from ${MINTED_TOKEN_VARIABLE} where that is set. Otherwise it reads this computer's token for the platform's address from its credential file, which ${LOGIN_SUBCOMMAND} and ${AUTHORIZE_SUBCOMMAND} write, and sends it only to that address. Else it reads ${PROVISION_CREDENTIAL.claim}. With none, it keeps a verifier, and prints the challenge and the submit_manifest call naming local_run and ${CODE_CHALLENGE_MEMBER}`;
6340
6403
  var NOTHING_REMINTED = "Nothing was re-minted, and the environment file is as it stood.";
6341
6404
  var CLAIM_FALLBACK_ERRORS = Object.freeze(["authentication_required", "secret_grant_not_admitted", "secret_grant_expired", "secret_grant_spent"]);
6342
6405
  var claimRefusedSentence = (origin, error) => `This computer's pending verifier was presented to ${origin}, which holds no provision grant it claims (${error}), so nothing was re-minted, and the first act follows.`;
6343
6406
  var PROVISION_BARE_LINE_WORDS = commandLineOf(DEFAULT_COMMAND_ORIGIN, PROVISION_SUBCOMMAND, { options: [[PROVISION_OPTION.application, "<application id>"]] });
6344
6407
  var freshLineOf = (io2, application, origin, envFile) => provisionLineFor(io2, { origin, application, ...envFile !== void 0 ? { envFile } : {} });
6345
- var freshLineSteps2 = (line) => `${line} with nothing piped, and where it prints a submit_manifest call, make that call from your tool and run the line it answers as given`;
6408
+ var freshLineSteps2 = (line) => `${line} with nothing piped. Where it prints a submit_manifest call, make that call from your tool and run the line it answers as given`;
6346
6409
  var provisionAgainOf = (line) => `Run ${freshLineSteps2(line)}.`;
6347
6410
  var againSteps = (kind, line) => kind === "grant" ? `run ${freshLineSteps2(line)}` : "run the line again";
6348
6411
  var remintAgainSentence = (kind, line) => {
6349
6412
  const steps = againSteps(kind, line);
6350
- return `${steps[0].toUpperCase()}${steps.slice(1)}: it re-mints both credentials and writes the file.`;
6413
+ return `${steps[0].toUpperCase()}${steps.slice(1)}. It re-mints both credentials and writes the file.`;
6351
6414
  };
6352
6415
  var envFileNameRefusalOf = (standing) => `${PROVISION_OPTION.envFile} names the environment file ${ENVIRONMENT_FILE_NAME} or ${ENVIRONMENT_FILE_NAME}.<name>, the names every zip the command or deploy_files builds leaves out, so the credentials it holds never ride one.${standing ? ` A file stands at the name given, and an earlier run may have written credentials into it: move its lines into ${ENVIRONMENT_FILE_NAME} and delete it.` : ""} ${NOTHING_REMINTED}`;
6353
6416
  var provisionOptionsOf = (call, cwd, stands = () => false) => {
@@ -6364,7 +6427,7 @@ var provisionOptionsOf = (call, cwd, stands = () => false) => {
6364
6427
  return { application, envFile, origin: origin.origin, claim: call.flags.has(PROVISION_CLAIM_FLAG) };
6365
6428
  };
6366
6429
  var APPLICATION_FOLDER_MARKS = Object.freeze(["package.json", "manifest.json"]);
6367
- var outsideApplicationWarningOf = (folder) => `warning: ${folder} holds neither ${APPLICATION_FOLDER_MARKS[0]} nor ${APPLICATION_FOLDER_MARKS[1]}, so it may not be the application's folder, and the environment file was written there all the same. A local run reads the environment file from the folder it runs in unless its line names one with ${PROVISION_OPTION.envFile}: move the file into the application's folder, or name it on the line that starts the run.`;
6430
+ var outsideApplicationWarningOf = (folder) => `warning: ${folder} holds neither ${APPLICATION_FOLDER_MARKS[0]} nor ${APPLICATION_FOLDER_MARKS[1]}, so it may not be the application's folder, and the environment file was written there all the same. A local run reads the environment file from the folder it runs in unless its line names one with ${PROVISION_OPTION.envFile}. Move the file into the application's folder, or name it on the line that starts the run.`;
6368
6431
  var outsideApplicationFolder = (io2, envFile) => APPLICATION_FOLDER_MARKS.every((mark) => {
6369
6432
  try {
6370
6433
  return io2.stat(join9(dirname5(envFile), mark))?.folder !== false;
@@ -6469,7 +6532,7 @@ var factsOf = (member) => {
6469
6532
  var connectionSettingOf = (facts, password) => `postgresql://${encodeURIComponent(facts.roleName)}:${encodeURIComponent(password)}@${facts.host}:5432/${encodeURIComponent(facts.dbName)}?sslmode=verify-full`;
6470
6533
  var LIMIT_SHOWN_MAX = 80;
6471
6534
  var UNATTENDED_JOB_VARIABLE = "CI";
6472
- var afterOwnErrorBy = (line) => `a credential may or may not have been re-minted, and the environment file may not hold its value: ${line} run again with nothing piped re-mints both and writes the file, or prints the submit_manifest call whose line does`;
6535
+ var afterOwnErrorBy = (line) => `a credential may or may not have been re-minted, and the environment file may not hold its value. ${line} run again with nothing piped re-mints both and writes the file, or prints the submit_manifest call whose line does`;
6473
6536
  var PROVISION_AFTER_OWN_ERROR = afterOwnErrorBy(`${PROVISION_BARE_LINE_WORDS}, with the ${PROVISION_OPTION.origin} and ${PROVISION_OPTION.envFile} the line named,`);
6474
6537
  var provisionAfterOwnError = (call, io2) => {
6475
6538
  try {
@@ -6602,7 +6665,7 @@ var pendingVerifierOf = (io2, origin) => {
6602
6665
  var PROVISION_CHALLENGE_HEAD = "challenge: ";
6603
6666
  var PROVISION_CALL_HEAD = "call submit_manifest with:";
6604
6667
  var MANIFEST_MEMBER_WORDS = "the application's manifest, as your tool submits it";
6605
- var replacedProvisionRequestSentence = (origin, expiredAt) => `The request pending for ${origin} expired at ${expiredAt}, so a new one replaces it: a line answered against the old challenge is refused using nothing, and the submit_manifest call naming the new challenge below answers a fresh one.`;
6668
+ var replacedProvisionRequestSentence = (origin, expiredAt) => `The request pending for ${origin} expired at ${expiredAt}, so a new one replaces it. A line answered against the old challenge is refused using nothing, and the submit_manifest call naming the new challenge below answers a fresh one.`;
6606
6669
  var provisionFirstActLines = (origin, application, challenge, expiresAt, line) => [
6607
6670
  `To write this application's development settings from ${origin}, call submit_manifest from your tool naming the members below, then run the line it answers once, as given, in this folder, before its grant expires.`,
6608
6671
  `${PROVISION_CHALLENGE_HEAD}${challenge}`,
@@ -6703,7 +6766,7 @@ async function remintAndWrite(io2, { application, envFile, origin }, userAgent,
6703
6766
  if (facts !== null && limitCarried !== null) {
6704
6767
  const cause = limitMember ? "the plan's database-connection-limit holds no usable quantity, which platform staff set with set_plan_quota" : "the platform that answered serves no such member yet";
6705
6768
  io2.print(
6706
- `${envFile} holds ${facts.setting} and the platform settings this run re-minted, and no ${LOCAL_RUN_SETTING.databaseConnectionLimit}: ${PROVISION_ACTION}'s development_database answer carried ${limitCarried}, where the pool's maximum is a positive integer, so ${cause}. Until that changes the application's pool holds one connection; once it has, ${againSteps(read2.kind, read2.again)}.`
6769
+ `${envFile} holds ${facts.setting} and the platform settings this run re-minted, and no ${LOCAL_RUN_SETTING.databaseConnectionLimit}. ${PROVISION_ACTION}'s development_database answer carried ${limitCarried}. The pool's maximum is a positive integer, so ${cause}. Until that changes, the application's pool holds one connection. Once it has, ${againSteps(read2.kind, read2.again)}.`
6707
6770
  );
6708
6771
  io2.print(provisionNextLineOf(read2.next));
6709
6772
  return COMMAND_STATUS.failed;
@@ -6732,7 +6795,7 @@ var PROVISION_ROW = Object.freeze({
6732
6795
  nothing_started: "nothing was re-minted"
6733
6796
  },
6734
6797
  note: [
6735
- `Run ${PROVISION_BARE_LINE_WORDS} from the folder the application runs in. With no token for the address, it prints a challenge and the submit_manifest call naming local_run and ${CODE_CHALLENGE_MEMBER}; your tool makes that call and runs the line it answers once, as given, before its grant expires, which presents the grant with this computer's verifier. On a computer logged in, the bare line re-mints at once.`,
6798
+ `Run ${PROVISION_BARE_LINE_WORDS} from the folder the application runs in. With no token for the address, it prints a challenge and the submit_manifest call naming local_run and ${CODE_CHALLENGE_MEMBER}. Your tool makes that call and runs the line it answers once, as given, before its grant expires, which presents the grant with this computer's verifier. On a computer logged in, the bare line re-mints at once.`,
6736
6799
  `Each run revokes the development credentials the application had before it. A deployed development environment holds the revoked values until it restarts, so the line's last re-mint restarts it where development serves a version. Its redeploy takes both re-minted credentials from custody, the connection string and the platform credential, and does not count toward the day's deploys. Where a deploy of development is still in flight, the re-mint's answer names restart_application on development, and your tool calls it once that deploy ends. ${PROVISION_SUBCOMMAND} writes no ${PORT_SETTING}: ${RUN_SUBCOMMAND} sets it from ${RUN_OPTION.port}.`
6737
6800
  ],
6738
6801
  afterOwnError: provisionAfterOwnError,
@@ -6758,9 +6821,9 @@ var SCAFFOLD_TEMPLATE_FILES = Object.freeze({
6758
6821
  "",
6759
6822
  "## Where the rules are",
6760
6823
  "",
6761
- "Turn Zero Cloud serves its rules to a coding tool through its MCP server, `turnzero-cloud`, and they change with the platform, so none is repeated here.",
6824
+ "Turn Zero Cloud serves its rules to a coding tool through the MCP server `turnzero`, one connection to the products your account holds. The rules change with the platform, so none is repeated here.",
6762
6825
  "",
6763
- `- Where the server is not connected, connect it first. The platform's page "Connect your AI tool" says how.`,
6826
+ "- Where the server is not connected, set up Turn Zero Cloud first: https://turnzero.ai/cloud/getting-started/set-up/",
6764
6827
  "- Before you change or deploy this service, read the server's `deploy` skill.",
6765
6828
  "",
6766
6829
  "## What you run here",
@@ -7032,9 +7095,9 @@ var SCAFFOLD_TEMPLATE_FILES = Object.freeze({
7032
7095
  "",
7033
7096
  "## Where the rules are",
7034
7097
  "",
7035
- "Turn Zero Cloud serves its rules to a coding tool through its MCP server, `turnzero-cloud`, and they change with the platform, so none is repeated here.",
7098
+ "Turn Zero Cloud serves its rules to a coding tool through the MCP server `turnzero`, one connection to the products your account holds. The rules change with the platform, so none is repeated here.",
7036
7099
  "",
7037
- `- Where the server is not connected, connect it first. The platform's page "Connect your AI tool" says how.`,
7100
+ "- Where the server is not connected, set up Turn Zero Cloud first: https://turnzero.ai/cloud/getting-started/set-up/",
7038
7101
  "- Before you change or deploy this service, read the server's `deploy` skill.",
7039
7102
  "",
7040
7103
  "## What you run here",
@@ -7151,9 +7214,9 @@ var SCAFFOLD_TEMPLATE_FILES = Object.freeze({
7151
7214
  "",
7152
7215
  "## Where the rules are",
7153
7216
  "",
7154
- "Turn Zero Cloud serves its rules to a coding tool through its MCP server, `turnzero-cloud`, and they change with the platform, so none is repeated here.",
7217
+ "Turn Zero Cloud serves its rules to a coding tool through the MCP server `turnzero`, one connection to the products your account holds. The rules change with the platform, so none is repeated here.",
7155
7218
  "",
7156
- `- Where the server is not connected, connect it first. The platform's page "Connect your AI tool" says how.`,
7219
+ "- Where the server is not connected, set up Turn Zero Cloud first: https://turnzero.ai/cloud/getting-started/set-up/",
7157
7220
  "- Before you change or deploy this service, read the server's `deploy` skill, and before you change its schedule, the server's `schedule` skill.",
7158
7221
  "",
7159
7222
  "## What you run here",
@@ -7357,9 +7420,9 @@ var SCAFFOLD_TEMPLATE_FILES = Object.freeze({
7357
7420
  "",
7358
7421
  "## Where the rules are",
7359
7422
  "",
7360
- "Turn Zero Cloud serves its rules to a coding tool through its MCP server, `turnzero-cloud`, and they change with the platform, so none is repeated here.",
7423
+ "Turn Zero Cloud serves its rules to a coding tool through the MCP server `turnzero`, one connection to the products your account holds. The rules change with the platform, so none is repeated here.",
7361
7424
  "",
7362
- `- Where the server is not connected, connect it first. The platform's page "Connect your AI tool" says how.`,
7425
+ "- Where the server is not connected, set up Turn Zero Cloud first: https://turnzero.ai/cloud/getting-started/set-up/",
7363
7426
  "- Before you change or deploy this service, read the server's `deploy` skill, and before you change its sign-in or its AI call, the server's `add-sign-in` or `use-ai-allowance` skill.",
7364
7427
  "",
7365
7428
  "## What you run here",
@@ -8161,7 +8224,7 @@ var SCAFFOLD_OPTIONS = Object.freeze([
8161
8224
  name: SCAFFOLD_OPTION.resource,
8162
8225
  value: "<plural>",
8163
8226
  required: false,
8164
- description: `Under ${RESOURCE_TEMPLATES_NAMED}, the resource the service keeps, by its plural, the word of its table and its route: an ASCII lower-case letter, then ASCII lower-case letters and digits, at most 30 characters. It is never the word of the template's own route: ${perResourceTemplate((kept2) => kept2.routes)}. The files are written under its names where the template names notes, note, Notes, and Note, file names among them. Where absent, the service keeps notes. A template that keeps no resource refuses it.`
8227
+ description: `Under ${RESOURCE_TEMPLATES_NAMED}, the resource the service keeps, by its plural, the word of its table and its route. It is an ASCII lower-case letter, then ASCII lower-case letters and digits, at most 30 characters. It is never the word of the template's own route: ${perResourceTemplate((kept2) => kept2.routes)}. The files are written under its names where the template names notes, note, Notes, and Note, file names among them. Where absent, the service keeps notes. A template that keeps no resource refuses it.`
8165
8228
  },
8166
8229
  {
8167
8230
  name: SCAFFOLD_OPTION.singular,
@@ -8215,30 +8278,30 @@ var ROOT_TOOLS_UNCHANGED = `${SCAFFOLD_LINE_HEAD.unchanged}${TOOLS_FILE} at the
8215
8278
  var ROOT_TOOLS_FAILED = `${SCAFFOLD_LINE_HEAD.failed}${TOOLS_FILE} at the project's root, where a part of the file may stand. Add this sentence to that file, so a coding tool started at the root reads ${APPLICATION_FOLDER}/${TOOLS_FILE}: ${ROOT_SENTENCE}`;
8216
8279
  var ROOT_CLAUDE_UNCHANGED = `${SCAFFOLD_LINE_HEAD.unchanged}${CLAUDE_FILE} at the project's root. Claude Code reads that file and then reads no ${TOOLS_FILE} by itself, so add this sentence to it: ${ROOT_SENTENCE}`;
8217
8280
  var NEITHER_LEFT = Object.freeze({ tools: "written", claude: false });
8218
- var ROOT_TOOLS_STEP = `Add this sentence to ${TOOLS_FILE} at the project's root, which the scaffold did not change, so a coding tool started at the root reads ${APPLICATION_FOLDER}/${TOOLS_FILE}: ${ROOT_SENTENCE}`;
8219
- var ROOT_TOOLS_FAILED_STEP = `Add this sentence to ${TOOLS_FILE} at the project's root, which the scaffold could not write, so a coding tool started at the root reads ${APPLICATION_FOLDER}/${TOOLS_FILE}: ${ROOT_SENTENCE}`;
8220
- var ROOT_CLAUDE_STEP = `Add this sentence to ${CLAUDE_FILE} at the project's root, since Claude Code reads that file and then reads no ${TOOLS_FILE} by itself: ${ROOT_SENTENCE}`;
8281
+ var ROOT_TOOLS_STEP = `Add a sentence to ${TOOLS_FILE} at the project's root, which the scaffold did not change, so a coding tool started at the root reads ${APPLICATION_FOLDER}/${TOOLS_FILE}. The sentence to add: ${ROOT_SENTENCE}`;
8282
+ var ROOT_TOOLS_FAILED_STEP = `Add a sentence to ${TOOLS_FILE} at the project's root, which the scaffold could not write, so a coding tool started at the root reads ${APPLICATION_FOLDER}/${TOOLS_FILE}. The sentence to add: ${ROOT_SENTENCE}`;
8283
+ var ROOT_CLAUDE_STEP = `Add a sentence to ${CLAUDE_FILE} at the project's root, since Claude Code reads that file and then reads no ${TOOLS_FILE} by itself. The sentence to add: ${ROOT_SENTENCE}`;
8221
8284
  var APPLICATION_FORM_REFUSAL = `${SCAFFOLD_OPTION.application} names the application the service deploys to, by its id, a lowercase UUID, as create_application answers it. ${NOTHING_WRITTEN2}`;
8222
8285
  var RESOURCE_REFUSAL = Object.freeze({
8223
8286
  /** A plural outside SCAFFOLD_NAME_FORM. */
8224
8287
  resourceForm: `${SCAFFOLD_OPTION.resource} takes the plural of the resource the service keeps, the word of its table and its route: an ASCII lower-case letter, then ASCII lower-case letters and digits, at most 30 characters, such as orders. ${NOTHING_WRITTEN2}`,
8225
8288
  /** A singular outside SCAFFOLD_NAME_FORM. */
8226
- singularForm: `${SCAFFOLD_OPTION.singular} takes the singular of that resource, the word for one of its rows, in the form ${SCAFFOLD_OPTION.resource} takes: an ASCII lower-case letter, then ASCII lower-case letters and digits, at most 30 characters, such as order. ${NOTHING_WRITTEN2}`,
8289
+ singularForm: `${SCAFFOLD_OPTION.singular} takes the singular of that resource, the word for one of its rows, in the form ${SCAFFOLD_OPTION.resource} takes. That is an ASCII lower-case letter, then ASCII lower-case letters and digits, at most 30 characters, such as order. ${NOTHING_WRITTEN2}`,
8227
8290
  /** `--singular` with no `--resource`. */
8228
- noResource: `${SCAFFOLD_OPTION.singular} takes the singular of the resource ${SCAFFOLD_OPTION.resource} names, and the line names no ${SCAFFOLD_OPTION.resource}: name the plural with ${SCAFFOLD_OPTION.resource}, or leave ${SCAFFOLD_OPTION.singular} out. ${NOTHING_WRITTEN2}`,
8291
+ noResource: `${SCAFFOLD_OPTION.singular} takes the singular of the resource ${SCAFFOLD_OPTION.resource} names, and the line names no ${SCAFFOLD_OPTION.resource}. Name the plural with ${SCAFFOLD_OPTION.resource}, or leave ${SCAFFOLD_OPTION.singular} out. ${NOTHING_WRITTEN2}`,
8229
8292
  /** A plural that does not end in s, with no `--singular`. */
8230
- noClosingS: `${SCAFFOLD_OPTION.resource} takes a plural that ends in s where the line names no ${SCAFFOLD_OPTION.singular}, since the singular is then the plural without its closing s: name the singular with ${SCAFFOLD_OPTION.singular}, such as ${SCAFFOLD_OPTION.resource} people ${SCAFFOLD_OPTION.singular} person. ${NOTHING_WRITTEN2}`,
8293
+ noClosingS: `${SCAFFOLD_OPTION.resource} takes a plural that ends in s where the line names no ${SCAFFOLD_OPTION.singular}, since the singular is then the plural without its closing s. Name the singular with ${SCAFFOLD_OPTION.singular}, such as ${SCAFFOLD_OPTION.resource} people ${SCAFFOLD_OPTION.singular} person. ${NOTHING_WRITTEN2}`,
8231
8294
  /** The plural `s` alone, with no `--singular`: its singular would be empty. */
8232
- emptySingular: `${SCAFFOLD_OPTION.resource} takes a plural longer than s alone where the line names no ${SCAFFOLD_OPTION.singular}, since the singular, the plural without its closing s, is never empty: name the singular with ${SCAFFOLD_OPTION.singular}, or a longer plural. ${NOTHING_WRITTEN2}`,
8295
+ emptySingular: `${SCAFFOLD_OPTION.resource} takes a plural longer than s alone where the line names no ${SCAFFOLD_OPTION.singular}, since the singular, the plural without its closing s, is never empty. Name the singular with ${SCAFFOLD_OPTION.singular}, or a longer plural. ${NOTHING_WRITTEN2}`,
8233
8296
  /** A singular, given or derived, of `json` (#5225): the resource's
8234
8297
  * invalid error, invalid_<singular>, would then be invalid_json, the
8235
8298
  * error of a body that does not parse, and a caller could no longer
8236
8299
  * tell the two apart (PLD-L0-106). */
8237
- jsonSingular: `${SCAFFOLD_OPTION.singular} takes a singular other than json, since the service answers invalid_json for a body that does not parse and invalid_ with the singular for a row it refuses: name another singular with ${SCAFFOLD_OPTION.singular}, such as ${SCAFFOLD_OPTION.resource} jsons ${SCAFFOLD_OPTION.singular} document. ${NOTHING_WRITTEN2}`
8300
+ jsonSingular: `${SCAFFOLD_OPTION.singular} takes a singular other than json, since the service answers invalid_json for a body that does not parse and invalid_ with the singular for a row it refuses. Name another singular with ${SCAFFOLD_OPTION.singular}, such as ${SCAFFOLD_OPTION.resource} jsons ${SCAFFOLD_OPTION.singular} document. ${NOTHING_WRITTEN2}`
8238
8301
  });
8239
8302
  var RESOURCE_NONE_KEPT = `${SCAFFOLD_OPTION.resource} and ${SCAFFOLD_OPTION.singular} name the resource ${RESOURCE_TEMPLATES_NAMED} keep, and the template this line writes keeps none: leave them out, or name ${RESOURCE_TEMPLATE_CHOICES}. ${NOTHING_WRITTEN2}`;
8240
8303
  var UNKNOWN_TEMPLATE = `${SCAFFOLD_OPTION.template} names the template to write, and the command has no template of that name: it has ${listedAnd(SCAFFOLD_TEMPLATES)}, and it writes ${SCAFFOLD_DEFAULT_TEMPLATE} where the line names none. ${NOTHING_WRITTEN2}`;
8241
- var ownRouteRefusal = (word) => `${SCAFFOLD_OPTION.resource} takes a plural other than ${word}, the word of a route the template serves itself: name another plural. ${NOTHING_WRITTEN2}`;
8304
+ var ownRouteRefusal = (word) => `${SCAFFOLD_OPTION.resource} takes a plural other than ${word}, the word of a route the template serves itself. Name another plural. ${NOTHING_WRITTEN2}`;
8242
8305
  var JSON_SINGULAR = "json";
8243
8306
  var resourceNamesOf = (call, template) => {
8244
8307
  const plural = call.named[SCAFFOLD_OPTION.resource];
@@ -8259,7 +8322,7 @@ var resourceNamesOf = (call, template) => {
8259
8322
  var CARRIED_FIELDS = Object.freeze([Object.freeze({ name: "title", kind: "text" })]);
8260
8323
  var FIELD_KINDS_CLAUSE = `the kind ${orListed(SCAFFOLD_FIELD_KINDS)}`;
8261
8324
  var COLUMN_MEANING = Object.freeze({ id: "the key column", owner: "the column of the row's owner" });
8262
- var reservedFieldRefusal = (columns) => `${SCAFFOLD_OPTION.fields} takes a field name other than ${columns.join(" or ")}, ${listedAnd(columns.map((column) => COLUMN_MEANING[column] ?? `the column ${column}`))} the migration writes itself, and ${FIELD_KINDS_CLAUSE}: name the field another way. ${NOTHING_WRITTEN2}`;
8325
+ var reservedFieldRefusal = (columns) => `${SCAFFOLD_OPTION.fields} takes a field name other than ${columns.join(" or ")}, ${listedAnd(columns.map((column) => COLUMN_MEANING[column] ?? `the column ${column}`))} the migration writes itself, and ${FIELD_KINDS_CLAUSE}. Name the field another way. ${NOTHING_WRITTEN2}`;
8263
8326
  var FIELD_REFUSAL = Object.freeze({
8264
8327
  /** A field with no colon or more than one, an empty field among them. */
8265
8328
  listForm: `${SCAFFOLD_OPTION.fields} takes fields separated by commas, each a name, a colon, and a kind, such as name:text,message:text, ${FIELD_KINDS_CLAUSE}. ${NOTHING_WRITTEN2}`,
@@ -8733,7 +8796,7 @@ var applicationStandsLines = (template, takeLines) => {
8733
8796
  return [
8734
8797
  first,
8735
8798
  ...takes.map(
8736
- (take, index) => `To add the ${take.entry} package to the application that stands, run this line at the project's root, then follow ${take.follow}, read_documentation's page ${take.page}: ${lines[index]}`
8799
+ (take, index) => `To add the ${take.entry} package to the application that stands, follow ${take.follow}, read_documentation's page ${take.page}. Run this line at the project's root first: ${lines[index]}`
8737
8800
  ),
8738
8801
  STANDS_DEPLOY_LINE
8739
8802
  ];
@@ -8801,14 +8864,16 @@ var takeMadeLines = (template, entries, lineOf) => {
8801
8864
  return [first, `${opening}, which takes ${taken} itself.`];
8802
8865
  }
8803
8866
  const lines = again.map(lineOf);
8804
- if (again.length === 1) return [first, `${opening}, then run this line at the project's root, which takes the ${again[0]} entry again into the new ${APPLICATION_FOLDER}/: ${lines[0]}`];
8867
+ if (again.length === 1) return [first, `${opening}. Then run this line at the project's root, which takes the ${again[0]} entry again into the new ${APPLICATION_FOLDER}/: ${lines[0]}`];
8805
8868
  return [
8806
8869
  first,
8807
- `${opening}, then run each of these ${LINE_COUNT_WORDS[lines.length] ?? lines.length} lines at the project's root, in order, which take the ${listedAnd(again)} entries again into the new ${APPLICATION_FOLDER}/:`,
8870
+ `${opening}. Then run each of these ${LINE_COUNT_WORDS[lines.length] ?? lines.length} lines at the project's root, in order, which take the ${listedAnd(again)} entries again into the new ${APPLICATION_FOLDER}/:`,
8808
8871
  ...lines
8809
8872
  ];
8810
8873
  };
8811
- var STAGE_NOT_OWN = `Something that is not this run's own stands at ${STAGE_FOLDER} in the project's root, the name the scaffold writes under, an earlier run's files under another template or another resource name among it: move or remove ${STAGE_FOLDER}, then run the line again. ${NOTHING_WRITTEN2}`;
8874
+ var STAGE_NOT_OWN = `Something that is not this run's own stands at ${STAGE_FOLDER} in the project's root, the name the scaffold writes under. An earlier run's files under another template or another resource name may be among it. Move or remove ${STAGE_FOLDER}, then run the line again. ${NOTHING_WRITTEN2}`;
8875
+ var startedRootScaffoldRefusal = (names) => `The project's root holds ${startedWordsOf(names)} and no package.json, so an application may be started there, and the scaffold would write app/ beside it. To add a library package to that application, add its package.json at the root, then run ${LIBRARY_SUBCOMMAND} take there. To start a new service, run this line in a new folder, or name one with ${SCAFFOLD_OPTION.path}. ${NOTHING_WRITTEN2}`;
8876
+ var ROOT_PACKAGE_LINE = "A package.json stands at the project's root, so the new application goes in app/ beside it.";
8812
8877
  var folderRefusalOf = (io2, options, files, takeLines, lineOf) => {
8813
8878
  const { root } = options;
8814
8879
  for (let at = root; ; at = dirname6(at)) {
@@ -8828,6 +8893,8 @@ var folderRefusalOf = (io2, options, files, takeLines, lineOf) => {
8828
8893
  const taken = takeMadeEntriesOf(io2, app);
8829
8894
  return taken !== null ? takeMadeLines(options.template, taken, lineOf) : applicationStandsLines(options.template, takeLines);
8830
8895
  }
8896
+ const started = startedAtRootOf(io2, root);
8897
+ if (started.length > 0 && !started.includes("package.json")) return [startedRootScaffoldRefusal(started)];
8831
8898
  if (!heldInside(io2, root, app)) return [scaffoldLinkSentence(`The application's folder, ${APPLICATION_FOLDER}/,`)];
8832
8899
  const staged = io2.stat(stage);
8833
8900
  if (staged === null && danglingAt(io2, root, STAGE_FOLDER)) return [notOwn];
@@ -8916,7 +8983,7 @@ var ApplicationArrived = class extends Error {
8916
8983
  };
8917
8984
  var arrivedLine = (template, takeLines) => `${APPLICATION_FOLDER}/ took a file or a folder while the scaffold ran, so an application stands there and the template was not written${standsWayOn(template, takeLines)}`;
8918
8985
  var ARRIVED_NO_FOLDER_LINE = `Something that is no folder came to stand at ${APPLICATION_FOLDER} while the scaffold ran, and the template was not written: move it, then run the same line again.`;
8919
- var SCAFFOLD_AFTER_OWN_ERROR = `where the project's root holds no ${APPLICATION_FOLDER}/, or an empty one, the application was not written, and the same line run again writes it; where ${APPLICATION_FOLDER}/ holds the service's files, the ${LIBRARY_SUBCOMMAND} take line for each entry the template takes, run at the project's root, then npm test in ${APPLICATION_FOLDER}/, finish it where the template takes entries, and npm install and then npm test in ${APPLICATION_FOLDER}/ finish it where it takes none`;
8986
+ var SCAFFOLD_AFTER_OWN_ERROR = `where the project's root holds no ${APPLICATION_FOLDER}/, or an empty one, the application was not written, and the same line run again writes it. Where ${APPLICATION_FOLDER}/ holds the service's files, the ${LIBRARY_SUBCOMMAND} take line for each entry the template takes, run at the project's root, then npm test in ${APPLICATION_FOLDER}/, finish it where the template takes entries. Where it takes none, npm install and then npm test in ${APPLICATION_FOLDER}/ finish it`;
8920
8987
  var printEach = (io2, text) => {
8921
8988
  for (const line of text.split("\n")) io2.print(line);
8922
8989
  };
@@ -9055,12 +9122,14 @@ async function scaffold(call, io2) {
9055
9122
  if (arrived !== null) return refuse(...arrived);
9056
9123
  const toolsStands = standsAt(io2, root, TOOLS_FILE);
9057
9124
  const claudeStands = standsAt(io2, root, CLAUDE_FILE);
9125
+ const rootPackage = startedAtRootOf(io2, root).includes("package.json");
9058
9126
  let ended = false;
9059
9127
  release = io2.whenEnded(() => {
9060
9128
  ended = true;
9061
9129
  printEach(io2, signalEndedLine(stateNow(), template, takeLines));
9062
9130
  });
9063
9131
  reached = "writes";
9132
+ io2.print(rootPackage ? ROOT_PACKAGE_LINE : APPLICATION_IN_APP_LINE);
9064
9133
  if (io2.stat(root) === null) io2.makeFolder(root);
9065
9134
  if (held.fresh) io2.makeFolder(held.library);
9066
9135
  writeTemplate(io2, stage, app, composedFilesOf(files, held.packages, minute, options.application));
@@ -9126,9 +9195,9 @@ async function installAndTest(io2, app, template, taken, origin, left) {
9126
9195
  return COMMAND_STATUS.done;
9127
9196
  }
9128
9197
  var SCAFFOLD_CREDENTIAL = LIBRARY_CREDENTIAL;
9129
- var SCAFFOLD_READS = `under a template that takes library entries what library take reads, ${LIBRARY_READS}; and under a template that takes none, no credential`;
9198
+ var SCAFFOLD_READS = `what library take reads under a template that takes library entries: ${LIBRARY_READS}. Under a template that takes none, it reads no credential`;
9130
9199
  var SCAFFOLD_AFTER_LOGIN = `Once ${LOGIN_SUBCOMMAND} has printed authorized:, run this ${SCAFFOLD_SUBCOMMAND} line again. ${NOTHING_WRITTEN2}`;
9131
- var SCAFFOLD_SIGN_IN_WHY = `A template that takes library entries needs a sign-in, since the library's reads are under a credential; ${SCAFFOLD_DEFAULT_TEMPLATE}, which takes none, runs without one.`;
9200
+ var SCAFFOLD_SIGN_IN_WHY = `A template that takes library entries needs a sign-in, since the library's reads are under a credential. The ${SCAFFOLD_DEFAULT_TEMPLATE} template, which takes none, runs without one.`;
9132
9201
  var SCAFFOLD_ROW = Object.freeze({
9133
9202
  name: SCAFFOLD_SUBCOMMAND,
9134
9203
  summary: `Writes a new service from a template into a project, ${SCAFFOLD_DEFAULT_TEMPLATE} where the line names no ${SCAFFOLD_OPTION.template}. It writes the template's files under app/, runs npm install and npm test there, and prints the next steps. It starts a new application, and writes over no file. Some templates take library entries: database-service takes the Database entry, and web-app takes three. Such a template takes each entry as library take does, under the same credential and with the same checks, before it writes anything. It fills the manifest's packages member from the library folder's rows. With no credential, it writes nothing, and prints the login route and this line to run again once you are signed in. A template that takes no entry reads no credential.`,
@@ -9139,16 +9208,17 @@ var SCAFFOLD_ROW = Object.freeze({
9139
9208
  statuses: {
9140
9209
  done: "the files written and installed, the entries taken where the template takes any, and the tests passed",
9141
9210
  failed: "the files written, and npm install or the tests failed",
9142
- unknown: "the run stopped before its end, by an interrupt or another signal that ended npm, by an error of the command's own, or by something that came to stand at app while it wrote: the printed sentence names the way on",
9211
+ unknown: "the run stopped before its end. An interrupt or another signal ended npm, or the command met an error of its own, or something came to stand at app while it wrote. The printed sentence names the way on",
9143
9212
  nothing_started: "nothing was written"
9144
9213
  },
9145
9214
  note: [
9146
9215
  `Run the ${SCAFFOLD_SUBCOMMAND} line at the root of a new project, or name the root with ${SCAFFOLD_OPTION.path}, which the command makes where it does not stand. A line that names no ${SCAFFOLD_OPTION.template} writes ${SCAFFOLD_DEFAULT_TEMPLATE}, which takes no library entry and makes no request, and says so in a line before the files it wrote. Under scheduled-job, the minute of the schedule's cron in the manifest is the minute of the hour, in UTC, at which the run started.`,
9216
+ `${SCAFFOLD_SUBCOMMAND} writes the service in ${APPLICATION_FOLDER}/, and before the files it lists, says so and why. Where a package.json stands at the root, it writes ${APPLICATION_FOLDER}/ beside it all the same. It refuses, writing nothing, where the root holds src/ or a source file such as server.mjs and no package.json.`,
9147
9217
  `With ${SCAFFOLD_OPTION.application}, the manifest names that application in its application member, on the line after manifest_version, which binds the folder to it before any deploy: a deploy or check line naming another application is refused. Where absent, the first deploy writes the member.`,
9148
- `Under ${listedAnd(RESOURCE_TEMPLATES)}, with ${SCAFFOLD_OPTION.resource}, and ${SCAFFOLD_OPTION.singular} where the singular is not the plural without its closing s, it writes the same service under the resource's names, its table, its route, its functions, and its file names among them, and runs the tests on the files as written. It refuses, writing nothing, where the root's ${APPLICATION_FOLDER}/ holds any file or folder, and it takes no option that overwrites: where the template takes entries, its sentence names the ${LIBRARY_SUBCOMMAND} take line for each, which adds the package to an application that stands.`,
9149
- `A root that holds neither ${LIBRARY_FOLDER}/ nor ${POINTER_FILE} takes a ${LIBRARY_FOLDER}/ of its own. Where the root holds no ${TOOLS_FILE}, it writes one of one sentence, which sends a coding tool to ${APPLICATION_FOLDER}/${TOOLS_FILE}; it changes no file that stands at the root, and where an ${TOOLS_FILE} or a ${CLAUDE_FILE} stands there it prints the sentence to add.`,
9150
- `${SCAFFOLD_SUBCOMMAND} leaves ${COMMAND_CREDENTIAL_VARIABLES.join(" and ")} out of what npm install and npm test receive. An interrupt reaches npm, the command ends after it, and after an interrupted install the tests are not started. A signal that arrives after the command's first write and before npm starts is acted on once the writes are made: the command prints the way on, starts no npm, and ends with 128 and the signal's number.`,
9151
- `Where the tests fail, they failed on the files as written, and the printed line says to report it, naming the versions the library served where the template takes entries, and the template and the command's version where it takes none.`
9218
+ `Under ${listedAnd(RESOURCE_TEMPLATES)}, with ${SCAFFOLD_OPTION.resource}, it writes the same service under the resource's names, its table, its route, its functions, and its file names among them. Name ${SCAFFOLD_OPTION.singular} too where the singular is not the plural without its closing s. It runs the tests on the files as written. It refuses, writing nothing, where the root's ${APPLICATION_FOLDER}/ holds any file or folder, and it takes no option that overwrites. Where the template takes entries, its sentence names the ${LIBRARY_SUBCOMMAND} take line for each, which adds the package to an application that stands.`,
9219
+ `A root that holds neither ${LIBRARY_FOLDER}/ nor ${POINTER_FILE} takes a ${LIBRARY_FOLDER}/ of its own. Where the root holds no ${TOOLS_FILE}, it writes one of one sentence, which sends a coding tool to ${APPLICATION_FOLDER}/${TOOLS_FILE}. It changes no file that stands at the root, and where an ${TOOLS_FILE} or a ${CLAUDE_FILE} stands there it prints the sentence to add.`,
9220
+ `${SCAFFOLD_SUBCOMMAND} leaves ${COMMAND_CREDENTIAL_VARIABLES.join(" and ")} out of what npm install and npm test receive. An interrupt reaches npm, the command ends after it, and after an interrupted install the tests are not started. A signal that arrives after the command's first write and before npm starts is acted on once the writes are made. The command then prints the way on, starts no npm, and ends with 128 and the signal's number.`,
9221
+ `Where the tests fail, they failed on the files as written, and the printed line says to report it. It names the versions the library served where the template takes entries, and the template and the command's version where it takes none.`
9152
9222
  ],
9153
9223
  afterOwnError: SCAFFOLD_AFTER_OWN_ERROR,
9154
9224
  run: scaffold
@@ -9187,13 +9257,13 @@ var SESSION_OPTIONS = Object.freeze([
9187
9257
  name: SESSION_OPTION.endUser,
9188
9258
  value: "<end user id or label>",
9189
9259
  required: true,
9190
- description: "The test end user, by the id or the label create_test_end_users answered."
9260
+ description: "The test end user, by the id or the label test_end_users answered with act create."
9191
9261
  },
9192
9262
  {
9193
9263
  name: SESSION_OPTION.out,
9194
9264
  value: "<path>",
9195
9265
  required: true,
9196
- description: `The cookie jar file the session's cookie is written into, which curl -b reads. Its folder must stand. A file that stands there is refused unless the line names ${SESSION_OPTION.force}, and a path inside the folder the command runs in is refused where that folder holds package.json, since a deploy from it would upload the jar.`
9266
+ description: `The cookie jar file the session's cookie is written into, which curl -b reads. Its folder must stand. A file that stands there is refused unless the line names ${SESSION_OPTION.force}. A path inside the folder the command runs in is refused where that folder holds package.json, since a deploy from it would upload the jar.`
9197
9267
  },
9198
9268
  {
9199
9269
  name: SESSION_OPTION.origin,
@@ -9215,9 +9285,9 @@ var SESSION_CREDENTIAL = Object.freeze({
9215
9285
  call: `the ${SIGN_IN_TEST_END_USER_ACTION} call`,
9216
9286
  mintedToken: true,
9217
9287
  piped: false,
9218
- places: `the command reads no standard input: it reads a minted token from ${MINTED_TOKEN_VARIABLE} where it is set, as a tool connected by a minted token sets it from where its token is kept, or a job with no tool from its secret store, and otherwise this computer's token for the platform's address from its credential file, which ${LOGIN_SUBCOMMAND} and ${AUTHORIZE_SUBCOMMAND} write.`
9288
+ places: NO_INPUT_PLACES
9219
9289
  });
9220
- var SESSION_READS = `no standard input: a minted token from ${MINTED_TOKEN_VARIABLE} where it is set, and otherwise this computer's token for the platform's address from its credential file, which ${LOGIN_SUBCOMMAND} and ${AUTHORIZE_SUBCOMMAND} write, sent only to that address; with neither, it prints the variable route first and then, where the address is admitted, the login route`;
9290
+ var SESSION_READS = `no standard input. It reads a minted token from ${MINTED_TOKEN_VARIABLE} where that is set. Otherwise it reads this computer's token for the platform's address from its credential file, which ${LOGIN_SUBCOMMAND} and ${AUTHORIZE_SUBCOMMAND} write, and sends it only to that address. With neither, it prints the variable route first, then the login route where the address is admitted`;
9221
9291
  var missingOptionSentence = (option) => `${SESSION_SUBCOMMAND} needs ${option.name} ${option.value}, as the line a ${SIGN_IN_TEST_END_USER_ACTION} call answers names it. ${NOTHING_SENT_OR_WRITTEN}`;
9222
9292
  var ENVIRONMENT_REFUSAL = `${SESSION_OPTION.environment} names the environment the end user signs in to, ${COMMAND_ENVIRONMENTS.join(" or ")}. ${NOTHING_SENT_OR_WRITTEN}`;
9223
9293
  var OUT_STANDS_REFUSAL = `A file stands where ${SESSION_OPTION.out} names the cookie jar, and ${SESSION_SUBCOMMAND} replaces one only where the line names ${SESSION_OPTION.force}. Name a new file, or add ${SESSION_OPTION.force} to replace it. ${NOTHING_SENT_OR_WRITTEN}`;
@@ -9463,12 +9533,12 @@ var SESSION_ROW = Object.freeze({
9463
9533
  reads: SESSION_READS,
9464
9534
  statuses: {
9465
9535
  done: `the end user was signed in and the session's cookie written to the file ${SESSION_OPTION.out} names`,
9466
- failed: "the platform refused the sign-in, the printed lines naming the platform's error and detail, or the end user was signed in and the cookie jar could not be written, so the session's cookie was not kept",
9536
+ failed: "the platform refused the sign-in, and the printed lines name the platform's error and detail. Or the end user was signed in, and the cookie jar could not be written, so the session's cookie was not kept",
9467
9537
  unknown: "the sign-in call drew no answer, was redirected, failed, or drew an answer that is neither a refusal nor a session, and nothing was written",
9468
- nothing_started: `nothing was sent, or nothing was written: an option, the file ${SESSION_OPTION.out} names, or the credential was refused, no credential was read and the two routes to one were printed, the platform was too old, or the jar's folder admitted no write`
9538
+ nothing_started: `nothing was sent, or nothing was written. An option, the file ${SESSION_OPTION.out} names, or the credential was refused. Or no credential was read, and the two routes to one were printed. Or the platform was too old, or the jar's folder admitted no write`
9469
9539
  },
9470
9540
  note: [
9471
- `A session line is the one your tool's ${SIGN_IN_TEST_END_USER_ACTION} call answers where the platform serves that action, and it carries no credential. Run it once: it signs the test end user in and writes the session's cookie into the file ${SESSION_OPTION.out} names, in the cookie file form curl -b reads, so the session's value never passes through your tool. Requests then carry the cookie with curl -b and that path.`,
9541
+ `A session line is the one your tool's ${SIGN_IN_TEST_END_USER_ACTION} call answers where the platform serves that action, and it carries no credential. Run it once: it signs the test end user in and writes the session's cookie into the file ${SESSION_OPTION.out} names. The file is in the cookie file form curl -b reads, so the session's value never passes through your tool. Requests then carry the cookie with curl -b and that path.`,
9472
9542
  `${SESSION_SUBCOMMAND} writes the cookie jar under another name beside it, owner-only, and renames it into place, and it removes that file where the run ends before the rename. It writes over a file that stands only where the line names ${SESSION_OPTION.force}. It refuses a path inside the folder the command runs in where that folder holds package.json, since a deploy from it would upload the jar.`
9473
9543
  ],
9474
9544
  afterOwnError: `whether the end user was signed in is unknown, and a file ${SESSION_OPTION.out} names may now stand, so run the line again, adding ${SESSION_OPTION.force} where it does`,
@@ -9491,7 +9561,7 @@ var TOKEN_CREDENTIAL = Object.freeze({
9491
9561
  mintedToken: false,
9492
9562
  bare: `under ${TOKEN_ACTS[0]}, it reads none, and prints the challenge for a ${MINT_TOKEN_ACTION} call`
9493
9563
  });
9494
- var TERMINAL_RULE_SENTENCE = `${TOKEN_SUBCOMMAND} ${TOKEN_CLAIM_ACT} prints a token's value, so it runs only where its standard error is a terminal, as in a terminal of your own outside the AI coding tool, its standard output piped or not; here it is not, as under an AI coding tool's shell, so nothing was read and nothing was sent. Run the line yourself in a terminal outside the AI coding tool, piping it into your secret store's command where the token is a job's.`;
9564
+ var TERMINAL_RULE_SENTENCE = `${TOKEN_SUBCOMMAND} ${TOKEN_CLAIM_ACT} prints a token's value, so it runs only where its standard error is a terminal, as in a terminal of your own outside the AI coding tool, its standard output piped or not. Here it is not, as under an AI coding tool's shell, so nothing was read and nothing was sent. Run the line yourself in a terminal outside the AI coding tool, piping it into your secret store's command where the token is a job's.`;
9495
9565
  async function token(call, io2) {
9496
9566
  const claim = call.act === TOKEN_CLAIM_ACT;
9497
9567
  const say = claim ? io2.printError ?? io2.print : io2.print;
@@ -9526,7 +9596,7 @@ async function token(call, io2) {
9526
9596
  return COMMAND_STATUS.nothing_started;
9527
9597
  }
9528
9598
  io2.hide(code, REDACTED_TOKEN_CODE);
9529
- return completeAct(io2, origin.origin, "general", code, agent.userAgent, say, (minted) => io2.printValue(minted.value));
9599
+ return completeAct(io2, origin.origin, "general", { code }, agent.userAgent, say, (minted) => io2.printValue(minted.value));
9530
9600
  }
9531
9601
  var TOKEN_ROW = Object.freeze({
9532
9602
  name: TOKEN_SUBCOMMAND,
@@ -9539,10 +9609,10 @@ var TOKEN_ROW = Object.freeze({
9539
9609
  done: "the challenge printed, or the value printed once",
9540
9610
  failed: "the token minted was an authorized computer's, and is revoked where it could be: the printed lines name revoke_token",
9541
9611
  unknown: "the exchange drew no answer, or an answer that is not a refusal: list_tokens shows whether a token was minted",
9542
- nothing_started: "nothing was minted: an option, the credential file, the token code, or a standard error that is no terminal was refused, no request was pending, the platform was too old, or the exchange was refused"
9612
+ nothing_started: "nothing was minted. An option, the credential file, the token code, or a standard error that is no terminal was refused. Or no request was pending, the platform was too old, or the exchange was refused"
9543
9613
  },
9544
9614
  variables: [[ORIGIN_VARIABLE, AUTHORIZATION_ORIGIN_VARIABLE_LINE]],
9545
- note: [`${TOKEN_SUBCOMMAND} ${TOKEN_ACTS[0]} may run in a tool, since it prints nothing secret. ${TOKEN_SUBCOMMAND} ${TOKEN_ACTS[1]} is yours, run in a terminal outside the AI coding tool on the same computer as the same user, and never by a tool: it runs only where its standard error is a terminal, which yours stays when you pipe its standard output into your secret store's command, such as gh secret set ${MINTED_TOKEN_VARIABLE}. Read the line's origin before you run it.`],
9615
+ note: [`${TOKEN_SUBCOMMAND} ${TOKEN_ACTS[0]} may run in a tool, since it prints nothing secret. ${TOKEN_SUBCOMMAND} ${TOKEN_ACTS[1]} is yours, run in a terminal outside the AI coding tool on the same computer as the same user, and never by a tool. It runs only where its standard error is a terminal, which yours stays when you pipe its standard output into your secret store's command, such as gh secret set ${MINTED_TOKEN_VARIABLE}. Read the line's origin before you run it.`],
9546
9616
  afterOwnError: AUTHORIZE_AFTER_OWN_ERROR,
9547
9617
  run: token
9548
9618
  });
@@ -9787,6 +9857,7 @@ var processIo = () => ({
9787
9857
  `);
9788
9858
  },
9789
9859
  errorIsTerminal: process.stderr.isTTY === true,
9860
+ outputIsTerminal: process.stdout.isTTY === true,
9790
9861
  // The one value line (PLD-L0-94): a minted token's value alone, whole, on
9791
9862
  // standard output; any other text is written as print writes it.
9792
9863
  printValue: (value) => {
@@ -9896,7 +9967,7 @@ var STATUS_MEANINGS = Object.freeze([
9896
9967
  ["nothing_started", "nothing was started"]
9897
9968
  ]);
9898
9969
  var WINDOWS_SENTENCE = `On Windows, write ${WINDOWS_LINE_PROGRAM} for ${LINE_PROGRAM}, because Windows PowerShell refuses ${LINE_PROGRAM} where running scripts is disabled.`;
9899
- var QUOTED_PATH_SENTENCE = "On Windows, a path written between double quotes ends in no backslash: cmd and Windows PowerShell 5.1 read a backslash before the closing quote as keeping the quote, and the command there refuses a path that holds a double quote.";
9970
+ var QUOTED_PATH_SENTENCE = "On Windows, end a path written between double quotes with no backslash. cmd and Windows PowerShell 5.1 read a backslash before the closing quote as keeping the quote. The command there refuses a path that holds a double quote.";
9900
9971
  var ON_WINDOWS = process.platform === "win32";
9901
9972
  var pipedHead = (subcommand) => subcommand.credential === null || subcommand.credential.piped === false ? "" : subcommand.credential.bare !== void 0 || subcommand.credential.computerToken === true ? `[echo <${subcommand.credential.grant}> |] ` : `echo <${subcommand.credential.grant}> | `;
9902
9973
  var usageLineOf = (subcommand) => {
@@ -9927,7 +9998,7 @@ var pipedLinesOf = (subcommand) => {
9927
9998
  const credential = subcommand.credential;
9928
9999
  if (credential === null || credential.piped === false) return [];
9929
10000
  return [
9930
- ` ${subcommand.name} reads ${credential.aGrant} from standard input, as the line ${credential.call} answers pipes it in${credential.mintedToken ? `; and otherwise a minted token from ${MINTED_TOKEN_VARIABLE} where it is set, or this computer's token from its credential file${credential.claim !== void 0 ? `, else ${credential.claim}` : ""}` : credential.computerToken === true ? `; and otherwise this computer's token from its credential file, never a minted token from ${MINTED_TOKEN_VARIABLE}, whose being set refuses the run` : ""}${credential.bare !== void 0 ? `; ${credential.bare}` : ""}.`
10001
+ ` ${subcommand.name} reads ${credential.aGrant} from standard input${credential.pipes !== void 0 ? ` ${credential.pipes}` : `, as the line ${credential.call} answers pipes it in`}.${credential.mintedToken ? ` Otherwise it reads a minted token from ${MINTED_TOKEN_VARIABLE} where that is set, or this computer's token from its credential file${credential.claim !== void 0 ? `, else ${credential.claim}` : ""}.` : credential.computerToken === true ? ` Otherwise it reads this computer's token from its credential file. It never reads a minted token from ${MINTED_TOKEN_VARIABLE}, and refuses the run where that variable is set.` : ""}${credential.bare !== void 0 ? ` ${credential.bare.charAt(0).toUpperCase()}${credential.bare.slice(1)}.` : ""}`
9931
10002
  ];
9932
10003
  };
9933
10004
  var readsLinesOf = (subcommand) => subcommand.reads !== void 0 ? [` ${subcommand.name} reads ${subcommand.reads}.`] : [];
@@ -9942,7 +10013,8 @@ var originVariableLine = () => {
9942
10013
  };
9943
10014
  var USER_AGENT_LINE = ` ${USER_AGENT_VARIABLE} text appended to the command's user agent on each request.`;
9944
10015
  var ownVariableLinesOf = (subcommand) => (subcommand.variables ?? []).map(([name, does]) => ` ${name} under ${subcommand.name}, ${does}`);
9945
- var statusLineOf = (status, meaning, clauses, also) => ` ${COMMAND_STATUS[status]} ${meaning}${clauses.length > 0 ? `: ${clauses.join("; ")}` : ""}.${also !== void 0 ? ` ${also}` : ""}`;
10016
+ var statusLineOf = (status, meaning, clauses, also) => ` ${COMMAND_STATUS[status]} ${meaning}.${clauses.map((clause) => ` ${clause}.`).join("")}${also !== void 0 ? ` ${also}` : ""}`;
10017
+ var statusClauseOf = (name, clause) => `Under ${name}, ${clause}`;
9946
10018
  var noteLinesOf2 = (subcommand) => (subcommand.note ?? []).flatMap((paragraph) => ["", paragraph]);
9947
10019
  var usageBlockOf = (subcommandHelp) => [
9948
10020
  "Usage:",
@@ -9977,7 +10049,7 @@ var subcommandHelpOf = (subcommand, version = commandVersion()) => {
9977
10049
  lines.push(USER_AGENT_LINE, "", "Statuses:");
9978
10050
  for (const [status, meaning, also] of STATUS_MEANINGS) {
9979
10051
  const clause = subcommand.statuses[status];
9980
- if (clause !== void 0 || also !== void 0) lines.push(statusLineOf(status, meaning, clause !== void 0 ? [`under ${subcommand.name}, ${clause}`] : [], also));
10052
+ if (clause !== void 0 || also !== void 0) lines.push(statusLineOf(status, meaning, clause !== void 0 ? [statusClauseOf(subcommand.name, clause)] : [], also));
9981
10053
  }
9982
10054
  lines.push(...noteLinesOf2(subcommand), "", SHARED_HELP_SENTENCE);
9983
10055
  return lines.join("\n");
@@ -9990,7 +10062,7 @@ var grantArgumentSentence = () => "An argument holds a grant. The command never
9990
10062
  var tokenArgumentSentence = () => `An argument holds a minted token. The command never takes a credential from its arguments: it reads a minted token from ${MINTED_TOKEN_VARIABLE} alone. A tool connected by a minted token, or an unattended run, sets that variable for the one line, from where the tool keeps the token or from your CI's secret store. Nothing was sent and nothing was started.`;
9991
10063
  var NOTHING_STARTED2 = "Nothing was started.";
9992
10064
  var unquoted = (value) => value.length >= 2 && value.startsWith('"') && value.endsWith('"') ? value.slice(1, -1) : value;
9993
- var quoteInPathSentence = (name) => `${name} names a path, and its value holds a double quote, which no path on Windows holds. The usual cause is a path written with a backslash before its closing quote, which cmd and Windows PowerShell 5.1 read as keeping the quote, joining the arguments after it into the value. Write the path with no backslash at its end. ${NOTHING_STARTED2}`;
10065
+ var quoteInPathSentence = (name) => `${name} names a path, and its value holds a double quote, which no path on Windows holds. The usual cause is a backslash before the path's closing quote. cmd and Windows PowerShell 5.1 read it as keeping the quote, and join the arguments that follow into the value. Write the path with no backslash at its end. ${NOTHING_STARTED2}`;
9994
10066
  var emptyValueSentence = (name) => `${name} was given an empty value, as an unset shell variable gives. Name its value, or leave ${name} out where the line means its default. ${NOTHING_STARTED2}`;
9995
10067
  var valuePlacesOf = (argv2) => {
9996
10068
  const places = /* @__PURE__ */ new Set();
@@ -10072,6 +10144,9 @@ var nodeFloorRefusal = (found, version = commandVersion()) => {
10072
10144
  return major !== null && major < COMMAND_NODE_FLOOR ? nodeFloorSentence(version, found) : null;
10073
10145
  };
10074
10146
  var versionLineOf = (version, found) => `${TURNZERO_CLOUD_PACKAGE} ${version} (Node.js ${found})`;
10147
+ var SETUP_GUIDE = "https://turnzero.ai/cloud/getting-started/set-up/";
10148
+ var SETUP_PROMPT = "Set me up with Turn Zero Cloud and a small demo app. Read https://turnzero.ai/cloud/getting-started/set-up/index.md in full and follow the steps.";
10149
+ var showOnboarding = (io2) => io2.outputIsTerminal === true && !io2.env.CI;
10075
10150
  async function runGuarded(argv2, io2) {
10076
10151
  const found = io2.nodeVersion ?? process.versions.node;
10077
10152
  const version = commandVersion();
@@ -10083,6 +10158,8 @@ async function runGuarded(argv2, io2) {
10083
10158
  const parsed = parseArguments(argv2, io2.windows ?? ON_WINDOWS);
10084
10159
  if (parsed.kind === "help") {
10085
10160
  io2.print((parsed.subcommand === void 0 ? null : subcommandHelpText(parsed.subcommand.name, version)) ?? shortUsageText(version));
10161
+ if (parsed.subcommand === void 0 && showOnboarding(io2)) io2.print(`
10162
+ New to Turn Zero Cloud? Start here: ${SETUP_GUIDE}`);
10086
10163
  return COMMAND_STATUS.done;
10087
10164
  }
10088
10165
  if (parsed.kind === "version") {
@@ -10096,6 +10173,12 @@ async function runGuarded(argv2, io2) {
10096
10173
  const npx = "ranThroughNpx" in io2 && io2.ranThroughNpx === true;
10097
10174
  const help = npx ? npxFormOf(`${SERVED} --help`, originReadOf(io2.env[ORIGIN_VARIABLE])) : `${SERVED} --help`;
10098
10175
  say(`${io2.windows ?? ON_WINDOWS ? windowsLineOf(help) : help} prints the usage.`);
10176
+ if (argv2.length === 0 && showOnboarding(io2)) {
10177
+ say(`
10178
+ Get started: ${SETUP_GUIDE}`);
10179
+ say(`Paste this into Claude, ChatGPT, or Codex:
10180
+ ${SETUP_PROMPT}`);
10181
+ }
10099
10182
  return COMMAND_STATUS.nothing_started;
10100
10183
  }
10101
10184
  const upgrade = startUpgradeCheck(io2, parsed.subcommand.name, parsed.call.named, version);
@@ -10106,7 +10189,7 @@ async function runGuarded(argv2, io2) {
10106
10189
  }
10107
10190
  var outputOf = (argv2, io2) => argv2[0] === TOKEN_SUBCOMMAND && argv2[1] === TOKEN_CLAIM_ACT ? io2.printError ?? io2.print : io2.print;
10108
10191
  var NOTHING_REACHED = "no subcommand was reached, so nothing was started";
10109
- var ownErrorSentence = (error, afterOwnError = NOTHING_REACHED) => `The command stopped on an error of its own (${error instanceof Error ? error.message : String(error)}); ${afterOwnError}.`;
10192
+ var ownErrorSentence = (error, afterOwnError = NOTHING_REACHED) => `The command stopped on an error of its own (${error instanceof Error ? error.message : String(error)}). ${afterOwnError.charAt(0).toUpperCase()}${afterOwnError.slice(1)}.`;
10110
10193
  var ownErrorLineOf = (argv2, io2, error) => {
10111
10194
  const parsed = parseArguments(argv2, io2.windows ?? ON_WINDOWS);
10112
10195
  return ownErrorSentence(error, parsed.kind === "run" ? afterOwnErrorOf(parsed.subcommand, parsed.call, io2) : NOTHING_REACHED);