One of the first things I ran into with ColdCore that I didn't like was the fact that you could reference any object from any location as long as you knew the objnum or objname of the object. I went through several iterations in attempting to fix this problem. The current iteration seems to work pretty well, but changes the format of the context variable. This won't actually break anything, it will just mean that people will still be able to use their old contexts to look at remote objects until that context gets overwritten.

The first thing I did was move the it/him/her context checks from $foundation.match_environment() to $user.match_environment, as context is actually defined on $user. It ended up looking like this:

---
@program $foundation.match_environment() +access=pub -e=0
  arg str;
  var obj, env, found, match, target;
  
  if (!str)
      throw(~objnf, "No object specified.", str);
  str = str.strip_article();
  
  // Handle special cases.
  if (str in ["me", "my"]) {
      return this();
  } else if (str[1] == "$" || str[1] == "#") {
      return (> $object_lib.to_dbref(str) <);
  } else if (str[1] == "~") {
      str = str.subrange(2);
      if (str[1] != "~")
          return $user_db.match_begin(str);
  }
  
  // Start matching
  found = [];
  env = .environment();
  
  // special case ordinal references
  if ((match = $parse_lib.ordinal_reference(str)))
      return env.match_nth(@match);
  if ((match = $parse_lib.possessive_reference(str))) {
      if (match[1] == "me")
          obj = this();
      else
          obj = (> env.match_object(match[1]) <);
      if (!obj.match_name(str)) {
          catch ~objnf, ~ambig, ~range {
              env = (| obj.contents() |) || [];
              if ((found = $parse_lib.ordinal_reference(match[2])))
                  return (> env.match_nth(@found) <);
              else
                  return (> env.match_object(match[2]) <);
          } with {
              if (error() == ~objnf)
                  throw(~objnf, obj.name() + " does not have " + match[2].add_indefinite() + ".");
              else if (error() == ~ambig)
                  throw(~ambig, "\"" + str + "\" can match " + traceback()[1][3].mmap('namef, 'ref).to_english("", " or ") + ".");
              else
                  throw(~objnf, obj.name() + "'s what?");
          }
      }
  }
  catch any {
      return (> env.match_object(str) <);
  } with {
      if (error() == ~badfrob) {
          target = traceback()[1][3];
          obj = frob_value(target)['location];
          obj.del_frob_from_contents(target);
          throw(~badfrob, "Cleaned up bogus frob in your environment, try again..");
      }
      if (error() == ~objnf)
          throw(~objnf, "You do not see " + str.add_indefinite() + " anywhere.");
      if (error() == ~ambig) {
          found = filter obj in (traceback()[1][3]) where (obj.name() == str);
          if (listlen(found) == 1)
              return found[1];
          if (found)
              found = found.mmap('namef, 'ref).to_english("", " or ");
          else
              found = traceback()[1][3].mmap('namef, 'ref).to_english("", " or ");
          throw(~ambig, "\"" + str + "\" can match " + found + ".");
      }
      rethrow(error());
  }
.
---
In preparation for work on $user.match_environment() I then created a new method called .long_fingers() on $user and $programmer. The return value of this method is then used in $user.match_environment() to determine whether or not to allow usage of $/#/~ (1 for yes, 0 for no):
---
@program $user.long_fingers() +access=pub -e=0
  return 0;
.
@program $programmer.long_fingers() +access=pub -e=0
  return 1;
.
---
Finally, I changed $user.match_environment's handling of context checks. Instead of simply returning the contents of a successful context match, it overwrites str with a successful match. This is then passed along to $foundation.match_environment(). It uses a .long_fingers() check to prevent objnums and objnames getting passed. It ended up looking like this:
---
@program $user.match_environment() +access=pub
  arg str;
  var match, gend;
  
  if (!str)
      throw(~objnf, "No object specified.", str);
  str = str.strip_article();
  if ((str[1] == "$" || str[1] == "#" || str[1] == "~") && .long_fingers() == 0)
      throw(~objnf, "You do not see " + str.add_indefinite() + " anywhere.");
  if (str == "." && (match = (| context['last] |)))
      str = match;
  if ((match = (| (.remembered())[str] |)))
      str = match;
  if (str in ["it", "him", "her"] && (match = (| context[str] |)))
      str = match;
  match = (> pass(str) <);
  if (match.has_ancestor($thing)) {
      gend = (| match.gender() |);
      if (gend)
          context = context.add(gend.pronoun('po), str);
  }
  if (type(context) == 'dictionary)
      context = context.add('last, str);
  return match;
.
---
Update (4/5/2000): I forgot to mention it here, but you will also need to change the command template for @remember to "@remember <any> as <any>", as well as remove the .namef() calls from $user.remember_cmd(), $user.forget_cmd(), and $user.remembered_cmd().
todd@idleminds.org