atris 3.74.3 → 3.74.4

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.
Files changed (2) hide show
  1. package/lib/yes-lock.js +36 -9
  2. package/package.json +1 -1
package/lib/yes-lock.js CHANGED
@@ -674,21 +674,42 @@ const PUSH_HINT = 'a branch push runs without a yes as: git push origin <branch>
674
674
 
675
675
  // git reads, plus local work that cannot move a ref other than the branch it is on
676
676
  const GIT_SEALED_READS = new Set(['status', 'diff', 'log', 'show', 'blame', 'rev-parse', 'ls-files', 'grep', 'describe', 'rev-list', 'merge-base', 'cat-file', 'ls-tree', 'show-ref', 'for-each-ref', 'shortlog', 'check-ignore', 'help', 'version']);
677
- const GIT_SEALED_LOCAL = new Set(['add', 'rm', 'mv', 'restore']);
677
+ const GIT_SEALED_LOCAL = new Set(['add', 'rm', 'mv', 'restore', 'update-index', 'write-tree']);
678
678
  const GIT_SEALED_GLOBALS = new Set(['--no-pager', '-P', '--no-optional-locks', '--literal-pathspecs', '--version', '--help', '-h']);
679
679
  // the shape of a branch name git accepts, without the corners that read as something else
680
680
  const BRANCH_NAME = /^(?!-)(?!\.)(?!.*\.\.)(?!.*\/\/)(?!.*\/\.)(?!.*@\{)(?!.*\.lock(?:\/|$))[A-Za-z0-9._/-]+(?<![./])$/;
681
681
 
682
- // Only -C and a few output switches go before the command. -c,
683
- // --config-env, and --exec-path are held: config can name a program git runs
684
- // (core.fsmonitor, core.pager), and git puts its own folder first on PATH for
685
- // that program, so a git inside it would skip the wrapper.
682
+ // -c a woken run may pass: a value that only turns something off, or a key
683
+ // that only changes how output looks. The engines harden their own git calls
684
+ // this way (hooks, fsmonitor, askpass, protocols, gc all off). A -c that
685
+ // names a program, path, command, alias, helper, pager, editor, or route is
686
+ // held, since git runs that program with its own folder first on PATH, where
687
+ // a git inside it skips the wrapper; so are the keys whose value is a name,
688
+ // URL, or refspec (alias, remote, url, push, include, credential, branch
689
+ // routing), where even an empty value can reroute (url.<x>.insteadOf=).
690
+ const GIT_DISPLAY_KEYS = new Set(['format.pretty', 'log.showsignature', 'status.showuntrackedfiles', 'core.quotepath', 'core.safecrlf', 'safe.barerepository', 'color.ui']);
691
+ const GIT_ROUTE_KEYS = /^(alias|remote|url|push|include|includeif|credential)\.|^branch\..+\.(remote|pushremote|merge)$/;
692
+
693
+ function sealedGitConfigOk(pair) {
694
+ const eq = String(pair).indexOf('=');
695
+ const key = (eq < 0 ? String(pair) : String(pair).slice(0, eq)).trim().toLowerCase();
696
+ const value = eq < 0 ? 'true' : String(pair).slice(eq + 1).trim();
697
+ if (GIT_DISPLAY_KEYS.has(key)) return true;
698
+ if (key === 'core.hookspath') return value === '/dev/null';
699
+ if (GIT_ROUTE_KEYS.test(key)) return false;
700
+ return /^(|false|never|0|no|off)$/i.test(value);
701
+ }
702
+
703
+ // Only -C, -c that turns something off, and a few output switches go before
704
+ // the command. --config-env and --exec-path are held.
686
705
  function sealedGitPrefix(args) {
687
706
  const prefix = [];
688
707
  for (let i = 0; i < args.length; i += 1) {
689
708
  const a = args[i];
690
- if (a === '-C') {
691
- prefix.push(a, String(args[i + 1] === undefined ? '' : args[i + 1]));
709
+ if (a === '-C' || a === '-c') {
710
+ const value = String(args[i + 1] === undefined ? '' : args[i + 1]);
711
+ if (a === '-c' && !sealedGitConfigOk(value)) return { bad: `-c ${value}` };
712
+ prefix.push(a, value);
692
713
  i += 1;
693
714
  continue;
694
715
  }
@@ -726,9 +747,11 @@ function sealedGit(args, ctx) {
726
747
  if (!p.sub) return pass();
727
748
  if (GIT_SEALED_READS.has(p.sub) || GIT_SEALED_LOCAL.has(p.sub)) return pass();
728
749
  // the questions below are asked of the repo the command names
729
- const repo = ctx.forRepo(p.prefix.filter((a, i, all) => a === '-C' || all[i - 1] === '-C'));
750
+ const repo = ctx.forRepo(p.prefix.filter((a, i, all) => a === '-C' || a === '-c' || all[i - 1] === '-C' || all[i - 1] === '-c'));
730
751
  const rest = p.rest;
731
752
  switch (p.sub) {
753
+ // a new repo has no remote; a template or a git folder elsewhere could bring hooks
754
+ case 'init': return rest.some(a => /^--(template|separate-git-dir)(=|$)/.test(a)) ? hold('git init with a template or a git folder elsewhere can bring hooks') : pass();
732
755
  case 'push': return sealedPush(p, repo);
733
756
  case 'fetch': return sealedFetch(rest, repo);
734
757
  case 'commit': return isMainRef(repo.currentBranch()) ? hold('a commit here would land on master') : pass();
@@ -764,7 +787,9 @@ function sealedPush(p, repo) {
764
787
  words.push(a);
765
788
  }
766
789
  if (words.length !== 2 || words[0] !== 'origin') return hold(`a handed-off job pushes one branch to origin; ${PUSH_HINT}`);
767
- const head = words[1].match(/^HEAD:refs\/heads\/(.+)$/);
790
+ // HEAD:<branch> is written out as HEAD:refs/heads/<branch>, so a name that
791
+ // matches a tag on origin can never update the tag
792
+ const head = words[1].match(/^HEAD:(?:refs\/heads\/(?=.))?(?!refs\/)(.+)$/);
768
793
  const branch = head ? head[1] : words[1];
769
794
  if (!head && (branch.includes(':') || branch.startsWith('refs/'))) return hold(`git push ${words[1]} names more than a branch; ${PUSH_HINT}`);
770
795
  if (isMainRef(branch)) return hold(`git push to master lands on master; ${PUSH_HINT}`);
@@ -964,6 +989,8 @@ const ATRIS_SEALED = {
964
989
  function sealedAtris(args, missionId) {
965
990
  const [cmd = '', sub = ''] = args;
966
991
  if (args.length === 1 && ['--version', '-v', '--help', '-h'].includes(cmd)) return pass();
992
+ // the boot read: atris prints the welcome screen for its spec file and stops
993
+ if (args.length === 1 && (cmd === 'atris.md' || cmd.endsWith('/atris.md'))) return pass();
967
994
  const allowed = Object.prototype.hasOwnProperty.call(ATRIS_SEALED, cmd) ? ATRIS_SEALED[cmd] : null;
968
995
  if (!allowed) return hold(`atris ${cmd} is not on the list a handed-off job may run`);
969
996
  const subOk = allowed === true || ['help', '--help', '-h'].includes(sub)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "atris",
3
- "version": "3.74.3",
3
+ "version": "3.74.4",
4
4
  "description": "you say what you want in plain words. atris builds it, checks it, and shows you proof.",
5
5
  "mcpName": "io.github.atrislabs/atris",
6
6
  "main": "bin/atris.js",