The Joys Of Programming

http://research.microsoft.com/pubs/1...

Fascinating article, but can someone help with the symbols they use? I know logic and set symbols like for-all, member-of, etc., but they use some new ones and in an unfamiliar 'font' (representation).

Edwin wrote:

alias yolo='git commit -am "DEAL WITH IT" && git push -f origin master'

Oh god...

I finally got off my arse and wrote a Windows Phone 8 podcast app. Unfortunately Microsoft has competely f*cked up the in-built podcast support for people not in the US, so I wrote my own.

The result is Cloud Pod, a pretty lightweight app in terms of functionality, but it does everything I need and I'm pretty proud of it.

http://www.windowsphone.com/s?appid=...

IMAGE(http://www.malor.com/gamerswithjobs/real_shetland_pony.jpg)

Nice job, Erebus. Any preferred resources for learning about MVVM implementations? I spent Sunday fiddling around with a Windows 8 app i'm working on but found it hard to find good tutorials on the subject. It makes perfect sense conceptually, but implementation-wise, it's a little more vague.

RolandofGilead wrote:

http://research.microsoft.com/pubs/1...

Fascinating article, but can someone help with the symbols they use? I know logic and set symbols like for-all, member-of, etc., but they use some new ones and in an unfamiliar 'font' (representation).

Could you give some specific examples? I need more details on how far in depth to go. I don't see anything so far that isn't defined, but I know that the way in which some of these symbols are defined and used in PL theory is not itself always apparent to people new to the field.

The key insight is: When you see a symbol you don't now, it's probably defined here. And that includes whole sequences, which are defining new "mixfix" operators to express relations. For example:

We use type environments Γ, and define subtyping on environments (⊢ Γ ≺ Γ) in terms of subtyping for permissions
(⊢ pp), class types (⊢ TT), and permission-qualified types (⊢ tt) in Figure 4.

This is a bunch of definitions of new notation. Specifically, gamma (Γ) is used as a symbol to denote some type environment. (Gamma is often used for environments.) They're defining a subtype relationship between environments, which will be written as "⊢ Γ ≺ Γ", where the gammas represent places where an environment will be written. There's also a subtyping relationship for permissions p, for class types T, and for permission-qualified types t, which are being defined the same way.

The use of "⊢" is common in this sort of relation—but its meaning is not significant to the definition. The only thing that matters is that "⊢ foo ≺ bar" has been defined as the subtyping relation. This is just as if someone said "e + e", where e denotes an arithmetic expression, is defined to represent addition.

If we look at the figure, there's also a definition for what goes into type environments: "Γ ::= ∊ | Γ, x : t". That is, a type environment (gamma) is either empty (∊), or it's a previous environment gamma extended with a new entry "x : t". That is, an environment is either empty or a list of pairs of variables (x) and their types (t). (x and t are defined earlier in the figure as being examples of variables and types, respectively.)

I hope that was helpful. If you could call out specific things, I can answer about them. But that first step is realizing that most of the time, these are new notations being defined and used, not old notations that you're expected to already know. There are short-cuts (like gamma usually being used for environments of some sort, or "a : b" usually means that "the type of a is b". But, everything is generally defined. For example, "≺" is used here to denote subtyping, but there are plenty of other symbols that could be. "<:" is common. With "≺", I wasn't sure what it was and had to look. (And that may be part of the point: that they're defining a specific atypical subtyping relation, so they didn't want to use the common one. The reader should look for the definition to avoid misunderstanding.)

Hypatian wrote:
RolandofGilead wrote:

http://research.microsoft.com/pubs/1...

Fascinating article, but can someone help with the symbols they use? I know logic and set symbols like for-all, member-of, etc., but they use some new ones and in an unfamiliar 'font' (representation).

Could you give some specific examples? I need more details on how far in depth to go. I don't see anything so far that isn't defined, but I know that the way in which some of these symbols are defined and used in PL theory is not itself always apparent to people new to the field.

The key insight is: When you see a symbol you don't now, it's probably defined here. And that includes whole sequences, which are defining new "mixfix" operators to express relations. For example:

We use type environments Γ, and define subtyping on environments (⊢ Γ ≺ Γ) in terms of subtyping for permissions
(⊢ pp), class types (⊢ TT), and permission-qualified types (⊢ tt) in Figure 4.

This is a bunch of definitions of new notation. Specifically, gamma (Γ) is used as a symbol to denote some type environment. (Gamma is often used for environments.) They're defining a subtype relationship between environments, which will be written as "⊢ Γ ≺ Γ", where the gammas represent places where an environment will be written. There's also a subtyping relationship for permissions p, for class types T, and for permission-qualified types t, which are being defined the same way.

The use of "⊢" is common in this sort of relation—but its meaning is not significant to the definition. The only thing that matters is that "⊢ foo ≺ bar" has been defined as the subtyping relation. This is just as if someone said "e + e", where e denotes an arithmetic expression, is defined to represent addition.

If we look at the figure, there's also a definition for what goes into type environments: "Γ ::= ∊ | Γ, x : t". That is, a type environment (gamma) is either empty (∊), or it's a previous environment gamma extended with a new entry "x : t". That is, an environment is either empty or a list of pairs of variables (x) and their types (t). (x and t are defined earlier in the figure as being examples of variables and types, respectively.)

I hope that was helpful. If you could call out specific things, I can answer about them. But that first step is realizing that most of the time, these are new notations being defined and used, not old notations that you're expected to already know. There are short-cuts (like gamma usually being used for environments of some sort, or "a : b" usually means that "the type of a is b". But, everything is generally defined. For example, "≺" is used here to denote subtyping, but there are plenty of other symbols that could be. "<:" is common. With "≺", I wasn't sure what it was and had to look. (And that may be part of the point: that they're defining a specific atypical subtyping relation, so they didn't want to use the common one. The reader should look for the definition to avoid misunderstanding.)

IMAGE(http://i.imgur.com/59Vt6.gif)

Reaction GIFs are boring. Let's do math!

Hypatian wrote:

Reaction GIFs are boring. Let's do math!

Hypatian wrote:

Reaction GIFs are boring. Let's do math!

Co-op Artin's Algebra in Coq?

beanman101283 wrote:

Nice job, Erebus. Any preferred resources for learning about MVVM implementations? I spent Sunday fiddling around with a Windows 8 app i'm working on but found it hard to find good tutorials on the subject. It makes perfect sense conceptually, but implementation-wise, it's a little more vague.

Hmm, thats a hard one because I've been doing MVVM at work (Silverlight) for a year and a bit so I don't remember where I started learning it.

I'd look into using the MVVM Light framework to get you started.

Feel free to bug me if you need some help

MVVM is similar to MVC and MVP, except that some UI tasks, like showing message boxes, are exceptionally hard to do without using the codebehind... the purists will scream from the ivory tower that your view's code behind MUST BE EMPTY. Also, the primary benefit, ie view model and view re-use... I've rarely seen used. In my opinion it doesn't really offer much benefit over a traditional MVP pattern.

That being said, MVVM Light is a good framework. Caliburn Micro is pretty easy to get up and running as well. It's worth understanding MVVM, since it's the new hotness.

In honor of Hypatian's post, I'm creating a new Internet symbol, the Hypat: tl;dq == "Too long, didn't quote"

Thanks Hypatian, when put in English it was definitely understandable, now I just need to read the thing and go through the proofs. (I may be back).
Hopefully it will help in my hobby OS (task-based! also based entirely around my crazy language which is made for running on gpu's and other parallel hardware).

Also, ever wonder what happened to Intel's Larrabee?
http://www.anandtech.com/show/6017/i...
Xeon Phi Coprocessors, they're not GPU's and performance depends on a lot and they're really expensive but now a dream I've had for a while is finally true, the damn thing runs its own OS inside (Linux of course).
I heard that the cards can go up to 8 GB of memory, implying the cores inside are 64-bit.

bandit0013 wrote:

MVVM is similar to MVC and MVP, except that some UI tasks, like showing message boxes, are exceptionally hard to do without using the codebehind... the purists will scream from the ivory tower that your view's code behind MUST BE EMPTY. Also, the primary benefit, ie view model and view re-use... I've rarely seen used. In my opinion it doesn't really offer much benefit over a traditional MVP pattern.

That being said, MVVM Light is a good framework. Caliburn Micro is pretty easy to get up and running as well. It's worth understanding MVVM, since it's the new hotness.

It's like any framework/pattern, there are always purists screaming from their ivory towers.

Saying that, there is definitely things you can use to trigger UI tasks. In my WP8 app, I use the messaging (event aggregation) pipeline to perform navigation from the View Models and to trigger message boxes and other things like that.

I absolutely still have code in my code-behinds, but not much

Today I am reading MLF: Raising ML to the Power of System F (Botlan, Rémy 1993. PDF). Mmm. Juicy, juicy System F.

MLF paper wrote:

Remarkably, rule A-HYP is not reversible.

Aw, they named a rule after you. How cute.

Venting is okay here, right? Good.

At my office, we're in the middle of some changes. Normally I'm fine with change, but this is verging on chaos.

We've changed over from Gerrit to Atlassian Stash for our Git repo management needs. No training on Stash, and it promotes a rather different workflow from Gerrit, so all the people who aren't terribly Git-proficient are confused, and various teams are struggling to decide on conventions (partly due to team composition issues, described below).

We've also changed language focus from mostly Java and some Python to, well, anything goes! One of our architects built a prototype app in Ruby on Rails, and a team was tasked with extending that prototype. Trouble is, basically no one else apart from the architect knows Ruby at all! Because he didn't think about anyone else, that team is having to slog through learning a new language just to add to a throwaway prototype for a potential partner's demo. Some people are working in R, some in PHP, some are learning Python (for Django, even though we have plenty of experience in two other very capable web frameworks)... and almost no one is talking about how to share knowledge or integrate work. I've been pretty vocal about building RESTful APIs into projects from their inception, but I don't think anyone has really bought into the idea yet, and if I mentioned AMQP there would be a flicker of recognition in the eyes of only five people.

We also recently changed our company's business direction, deciding to head towards health informatics. Not that we have anyone in the organization with domain knowledge, which would be kind of helpful given the complexity of the field. We have zero clients and few leads, so there's a dearth of actual work to be done.

Lastly, we've also changed our team structure. We're in the middle of a weird limbo period where our head of development scrambled every team together to work on some one-off projects. Sometime next week, there's yet another full stop for all software devs (we started the year with two weeks of agile training and roadmap building) so we can all get together to talk about how to redistribute everyone into more permanent teams, because 23 mostly-junior devs in a face-to-face discussion will undoubtedly do an excellent job. Team composition is not helped by the fact that we've apparently chosen to subsidize a few hires who neither have an interest in health informatics, natural language processing, and machine learning nor can code their way out of a paper bag.

If you're wondering how this company hasn't collapsed, it's because there's some ungodly amount of funding behind it. I've heard that we could operate this way for, like, a decade without shutting down. But don't worry, we hired not one but two full-time "change management specialists", which I think puts us a little over 1 non-coder for every coder... in a company making no money and building no real products.

The silver lining is that I'm feeling strongly motivated to pursue my outside projects. I've got one project that I want to see become a production-quality web app at least by year's end (though by summer's end would be sweet), and I recently discovered Elixir which looks gorgeous so I'd like to figure out a way to contribute to that.

/exhale

@Cyranix

Well... if there's no direction and no work to be done, I would be studying like mad. I would get involved on linked in groups and work on building my network. Stable pay is great, but if you're unhappy you have the perfect opportunity to sharpen the saw and wait for a great opportunity.

bandit0013 wrote:

@Cyranix

Well... if there's no direction and no work to be done, I would be studying like mad. I would get involved on linked in groups and work on building my network. Stable pay is great, but if you're unhappy you have the perfect opportunity to sharpen the saw and wait for a great opportunity.

It also doesn't help tremendously that I'm married with pets, living on an island, and assuredly moving in about a year and a half (due to wife's career). I'm optimistic that my outside work and my participation in online communities will be sufficient saw-sharpening and networking.

Cyranix wrote:
bandit0013 wrote:

@Cyranix

Well... if there's no direction and no work to be done, I would be studying like mad. I would get involved on linked in groups and work on building my network. Stable pay is great, but if you're unhappy you have the perfect opportunity to sharpen the saw and wait for a great opportunity.

It also doesn't help tremendously that I'm married with pets, living on an island, and assuredly moving in about a year and a half (due to wife's career). I'm optimistic that my outside work and my participation in online communities will be sufficient saw-sharpening and networking.

Where are you going to be moving? We'd probably hire you in a second.

Cyranix wrote:

We've also changed language focus from mostly Java and some Python to, well, anything goes! One of our architects built a prototype app in Ruby on Rails, and a team was tasked with extending that prototype. Trouble is, basically no one else apart from the architect knows Ruby at all! Because he didn't think about anyone else, that team is having to slog through learning a new language just to add to a throwaway prototype for a potential partner's demo. Some people are working in R, some in PHP, some are learning Python (for Django, even though we have plenty of experience in two other very capable web frameworks)

I feel your pain. The "anything goes" attitude is utterly, endlessly rampant in academic comp.sci. projects. Looking at the 10 people in the group I work in and I'm pretty sure not one of us is using the same and languages/techs as the next one. My boss, for instance knows C (and some seriously out of date Perl), so he does everything in C no matter if there are more appropriate technologies available. I've seen plenty of things that could be short scripts rendered as 100s or 1000s of lines of C. The general consequence of this is that a typical day will see me coding, hacking and bug fixing in 3+ languages and so it's been in every group I've worked in.

Also no source control and no automated testing.

On the flipside is that a lot of my current project has to unify our web framework. That's now implemented in just 2 technologies (Ruby and Java) but can accommodate executables in anything. It's passably elegant in that it allows everyone to build new, finished software and slot it in to our web offerings with minimal fuss. Along the way I've brought source control in to the group and some limited testing so we now have a little blackbox/compliance testing (no unit testing as my boss dug his heels in an said no one was to do that, go figure)

Cyranix wrote:

We also recently changed our company's business direction, deciding to head towards health informatics. Not that we have anyone in the organization with domain knowledge, which would be kind of helpful given the complexity of the field. We have zero clients and few leads, so there's a dearth of actual work to be done.

I work in a tangentially related field and can tell you; Good Luck with that.

Bonus_Eruptus wrote:

Where are you going to be moving? We'd probably hire you in a second.

He is an ex-Austin-ite already.

Sadly, I shan't be returning to the wonderful city of Austin, in all likelihood. My wife is a neuroscience postdoc who will be undertaking her search for a professor position soon, and apparently it's an unwritten rule that you can't do {undergrad, grad, post-doc, professor} at any of the same institutions. We go wherever she can find work, within reason (i.e. somewhere that will afford me a decent job market too), but that's very much up in the air at present. You're very kind to make the suggestion, Bonus.

In the meantime, I'm going to try to keep my motivation for outside projects strong and post about it in here to keep myself honest. First step is training a custom part-of-speech tagger (ultimately headed towards specialized entity recognition -- all of the Reuters-trained default models suck for my corpus), which I hope to code the majority of this weekend. I don't need great performance at this stage, just enough to build up a workflow from raw text to labeled entity chunks, so I can get by with just a handful of manually annotated documents. Increasing the size of the manually annotated corpus is something that can be done later, and from experience I know how much fun it is... so I'm already considering Mechanical Turk.

Cyranix wrote:

we hired not one but two full-time "change management specialists"

Are their names both Bob?

boogle wrote:
Bonus_Eruptus wrote:

Where are you going to be moving? We'd probably hire you in a second.

He is an ex-Austin-ite already.

Implying that we only have one location.

As an update, I had a meeting with a very influential CIO today and he's going to get me in front of some other CIOs in the area about my guild concept. The idea of sponsorship of an apprenticeship style organization that they could pluck good workers from seems to be an attractive one.

One thing I've been kicking around in my head... what sorts of activities would you engage in to turn a junior into a mid, or a mid into a senior?

So, at work we're looking at adding some new tools to our process. Part of what's involved here is getting people from more areas working on things using the same tools.

(Important note: We cannot use an external tool like Bitbucket or github or Google Code to host our primary development sources, for Reasons. So, any solution to our problems has to be software we can install locally, not an external service. Unfortunately, it seems like most of the best tools are services only, which is a bummer for us. As I'm complaining bitterly about Atlassian stuff, note that they bought Bitbucket, and if we could install that we would be pretty happy. But presumably it's built onto cloud techs or something and isn't really suited for deployment to customer sites. Or something. Very sad.)

We're currently using Mercurial for most of our VC, with some Subversion stuff that hasn't come over yet (but will). Members of my former team use a shared filesystem for storing our central backed-up repos of things. We access those repos directly via the FS. People in another former team access via a specific server, because there's a strong firewall involved, and some other pain (to enforce a quarantine against machines that store malicious code).

Anyway, we're looking at putting all of the repos together so that we're sure everyone has access to everything, and it's easier to get people from the former teams working together on both sets of code.

In addition, there's some desire to have us start using an issue tracker. My former team mostly does things using shared email folders, which works well for us, but again, that doesn't work well when we mix the teams together. Our team has resisted using JIRA in the past, even though word came down from On High that it was what we had available. Apparently, some of the pain we've dealt with in the past can be ameliorated if we have our *own* JIRA instance instead of the centrally-managed one, because then we don't have to go through week-long turnarounds to get changes made to projects by the people who have admin access. However, our impression is still that JIRA is rather sh*tty. The other former development team uses Trac. Another team that isn't in this developer pool really uses their own JIRA and has had some success.

In addition in addition, we'd like to implement some sort of code review system, just to make sure that more people are familiar with more different pieces of code. My former team, again, uses email for this sort of thing mostly--all pushes to the central repos (and svn repos) are logged to a shared IMAP folder, which we can browse through. We're not really good about reading a lot of it, though. So some more structure might be nice.

And finally, as developers, we're mostly interested in things that make our life easier, not harder. So things that make it easier to do things? Good. Things that maybe take a little more effort but gives us new capabilities? Good. Things that take just as much effort as doing it by hand? Kind of sh*tty.

Okay, so that's the setup. We've been evaluating Atlassian stuff, since some of that is in use in other places, including the JIRA that we never use, and the JIRA that that other team does use. We looked at FishEye and Crucible, and... they seem really really sh*tty. Like, FishEye doesn't really provide anything more than a simple hgweb setup (aside from minor integration with JIRA--although it tends to pick up random comments in our commits as JIRA issues, which is rather unhelpful. Thing-3.5.1 isn't issue [Thing-3].5.1, but thanks for the link. Very helpful.) Crucible doesn't seem to provide a code review mechanism that actually matches what we want to do. You can put comments in a commit to say "Hey, review this please", but the act of actually reviewing something doesn't do anything useful. Neither FishEye nor Crucible provides any repo-management features over the basic stuff, and in fact they: a) add an extra step of "register the repo with Atlassian stuff after putting it on the system", and b) don't support the idea that a single "project" could be associated with multiple repositories, either.

In short, the Atlassian stuff just doesn't seem like a good fit for us. We have a history of hate with the Atlassian tools we deal with so far, and go out of our way to avoid them because they get in the way so much. There's some potential that Confluence and JIRA could be made to suck less with more direct control, but these additional tools don't seem to provide anything new that we actually want. In short, Atlassian stuff seems cheap, but is overall crappy.

--

Now, things we've been looking at since FishEye + Crucible turned out to be so painful:

1) Phabricator seems interesting, and is freely available. The fact the the whole thing (including the [em]command-line tools[/em]) is written in PHP is kind of icky. But if it works, it works. Unfortunately, it's not super clear how well it works for Mercurial. I tried to do a pull-request style thing to evaluate how doing a code review on push/pull could work. "arc diff" creates a "differential patch", which can then be reviewed, and then "arc land" should theoretically apply approved patches to the main repo. Unfortunately, it seems like this stuff is very git-oriented. First, if I use "arc patch D###" to apply a differential diff to a repo, it collapses all of the individual checkins in the diff as a single checkin. It basically rebases for you. That's enforcing a specific workflow that's not really the way we do things. Worse, the "arc land" didn't work at all, because it assumed that the changes *must* be on a "feature branch". That's a good model for git, but not so much for Mercurial--particularly because Phabricator uses named branches in Mercurial for the purpose, which are way too heavy for that use. (Mercurial bookmarks are a better match for git branches.)

And even though they're in PHP, the presence of command-line tools is a real plus. Makes it easier to do emacs integration. Bwahaha.

So, that seems interesting, but not a super good match for how we're doing things. It's more or less layering a completely additional model of VC on top of an already existing VC system. It seems like if we used git it would be a better match, but since we use Mercurial, it's really not. It has some nice features, though, and is certainly better than the Atlassian stack.

Overall: This provides new capabilities that we don't already have, but using a model that's very different from how we're doing things so far. If we don't buy into that model, it doesn't really give us anything for the code review stuff, although it does handle issue tracking and source code browsing.

2) RhodeCode seems to be an attempt at an open-source version of the github/Bitbucket/Google Code. It provides a fork + pull-request model. It lets you easily make new repos on the server. It's not bad--but the UI is very clunky, and it's not super good, either. It feels like in a year or two it might be a good choice, but it's not there yet. As an example, pull requests can be made and can then be checked off on--but then you have to apply the changes manually. It doesn't even say "here's the hg command to run to do the pull, make sure to deal with conflicts and merge." It seems like they're working on that, but again... not there yet.

Another example of almost-but-not-quite is that it has issue tracker support, in that you can add a single regex to look for, and a URL to fill the regex matches into. But it would be nice if that was more generalized, so you could have multiple patterns and URLs. Still, that provides a point of entry if we wanted to, say, use JIRA for issue tracking and RhodeCode for managing repos and reviews.

Overall: This provides additional repository management capabilities that make it much easier to make new repos. It supports an increasingly common model for reviewing and merging changes. It doesn't provide issue tracking. And... it's clunky, at the moment, and not all of the fork/pull model is implemented.

3) The most promising thing to me and one coworker is Kiln. Fog Creek provides this cheaply as a service, and more expensively for a deployment you can stand up on your own servers. It doesn't support exactly the same fork/pull-request model, but what it does support seems like a better match for Mercurial in some ways. You can easily fork a repo on the server, and once you've done that it's trivial to say "please add a code review for all outgoing changes back to the forked repo" (or any other related repo, for that matter). Also in the web UI you can do the push or pull. So it would be pretty easy to fork, make changes, ask for a review of new changes to be pushed, get them signed off, and then push/pull the changes. When changes are merged to another repo, the reviews stay associated with the changes there--so you could even nuke the fork and still see that the changes had been reviewed and what was said about them.

Kiln doesn't do issue tracking itself, but does integrate strongly with FogBugz, which also costs some dough. FogBugz appears to do everything we need, with somewhat less restrictions than JIRA. It doesn't support all of the workflow features that JIRA supports, but... honestly, after looking at JIRA's workflow stuff, my recommendation was "do not touch". Unfortunately, if you want to do something like say "everything that goes to status X is assigned to person Y" in JIRA you *have* to touch the state machine and do a bunch of work. In FogBugz, that's about the only thing you can do, which is nice--it's more or less the only thing we want to do.

It's also possible to use a built-in CSS + Javascript greasemonkey like capability built into Kiln to adapt it to work with other tools. (i.e. I could write up some stuff to automatically highlight and link bug numbers from some other issue tracker using Javascript, store that on the Kiln server, and anybody else could trivially turn it on for their account. That's kind of slick.)

All of this seems very well put together and professional. It's the same software they're using for their Kiln service, and it shows in the polish it has. Everything is built to be used through the web interfaces, so there's no going around the system or into admin panels to make repos in some other way (as appears in both the Atlassian stuff and Phabricator). Everything that is there has good usability and works (unlike RhodeCode).

Oh, and FogBugz provides some basic wiki stuff, which means it's an alternative to the hated Confluence, too. Win win.

Overall: This maps very well onto Mercurial (which makes sense, since it only supports Mercurial). It provides additional repository management features that we want. It integrates with a similarly high-quality issue tracker (and with a little work, with other tools). It's not free, and it's more expensive than the Atlassian stuff. But it seems worth the additional cost. (Actually, I take that back. It costs more up-front, but that's a *purchase*, not a limited-time license. The second year, Fog Creek stuff catches up in price. Third year, it wins hands down. That might make this discussion easier...)

----

Anyway, short form is: I think I'm favoring suggesting we at least try out Kiln and FogBugz. We're going to be managing our own stuff anyway, which means we shouldn't be bound by the tools that other groups prefer. These tools appear to do what we want quite well, and to give us new stuff we can do.

And my question to the group: Has anybody used FogBugz + Kiln? Any gotchas? What about other software I haven't mentioned? The killer features are repo management and code review, I'd say, done in a form that takes very little effort for a great addition of utility. Issue tracking is a side issue, but it would be nice to integrate. I have looked at other things I haven't mentioned, but they don't seem to cover the bases. But... yeah, I've probably missed something.

I got as far as "Can't use Github... blah blah blah... has to be software we can install locally, not an external service." and I was immediately ready to say GITLAB. Bam, done.

But it seems you're totally committed to HG, so I guess that's not much help? I haven't used Kiln, but I enjoyed the short time I spent playing with FogBugz. It was especially refreshing as I was coming from the stiflingly rigid world of Jira as well.

Yeah, I think we'd rather stay with Hg rather than git. They both provide mostly the same capabilities, but there are some major differences in how the details encourage you to get work done. Thanks for the pointer, though--it's worth at least looking at. I dunno, maybe I'll play around with writing a web-based repo management thing for Mercurial that doesn't suck. (Not for work, but just because.)

And thanks for mentioning that working with FogBugz was pleasant compared to JIRA. I think pretty much every system will expose some serious warts after you've been using it for a while--but JIRA etc... well, the warts seem to show up right away. So it's very good to hear that FogBugz wasn't that bad, even if you didn't use it long enough to find the eventual likely nasty bits.

One thing I've been kicking around in my head... what sorts of activities would you engage in to turn a junior into a mid, or a mid into a senior?

As far as Junior->Mid-Level, a lot of that is simply time and familiarity. Sure, your basic comp sci grad may have dabbled in a few programming languages and learned a bunch of algorithms, but most likely they haven't had access to the enterprise-level stuff (especially if they join a Microsoft shop) so they'll have a bunch of learning to do to get familiarity with the tools. Coding standards, SDLC, even disciplined use of source control are all things they'll need to pick up.

Mid->'Senior' is a much more difficult topic. Some believe that it's mostly 'soft' skills that make a senior engineer, and I think there's a lot of truth in that. Others believe that it's some magical level of technical wizardry, and yet more just use years of experience.

For me, a lot of it is about trust. Is this person someone I can describe a problem to and expect them to come up with a reasonable solution and reasonably accurate estimate with a minimum of review? Perhaps you could have some sort of system where devs personally vouch for other engineer's work.

One progression I've heard is along the lines of

Junior: works on moving beyond "just programming" (cf. Minase's comment) and "just getting something to work", as well as developing depth in one or two areas; accepts the solutions provided by superiors as gospel, more or less

Intermediate: continues to develop depth (more self-directed) and begins to develop breadth; needs less oversight to tackle challenges and takes on more complex work; recognizes many solutions for a given problem

Senior: has excellent depth in one or two key areas and impressive breadth to help tie everything into a consistent whole; capable of leadership on technically challenging work and mentorship of junior developers; commits to opinions about correct solutions based on better understanding of context

Super-Senior (a.k.a. Fellow, Associate, etc.): in addition to previous level's traits -- contributes to the state of the art in areas of expertise, participates frequently in the larger development community [e.g. talks at conferences], helps to set the technical vision for organization

with the title change happening upon demonstration of the skill level, instead of awarding a title change and asking people to grow into it. This progression has a similarity to Valve's "T-shaped employee" idea and the (simplified) William Perry model of intellectual development (there's a better presentation out there but I can't find it at the moment). As regards timing, I'd say that you can reach intermediate pretty quickly if you've got a good head on your shoulders and/or had a good education, but attaining senior often happens prematurely and probably should take a solid decade. [And this isn't a cranky old man's opinion!]