Face painting and historical Web development

I spent my last two weekends working with ancient web technologies. Anne decided she wanted to update her Happy Faces web to attract more face painting business. I agreed to create a form for customers to inquire about rates and availability. The hosting service only offered Python 2.4,  CGI, and sendmail.

I really did not want to write a script that I knew others had written. I just wanted to make a pretty little form to help Anne. I found one library that almost worked.  I knew I could write a better library, and I would not trust any library without a test suite. I decided to write my own that would manage the request and response form, sending emails, and storing them if sendmail failed. I wrote a simple means to define a schema of what fields are in the form and how to validate them. The test module even provides a test web server that runs the CGIs you place in the root directory. This was a fine meditative exercise, but I would not describe it as fun.

I did have fun creating Anne’s contact form. Defining the schema for her form took minutes, and it was painless to make changes as we discussed what was optional and what the wording should be. The web page is not historical, it is very modern in fact. It uses HTML 5 form inputs and JavaScript to collect the information. The new  form inputs work in HTML 4 browsers like IE and FireFox, but HTML 5 browsers like Chromium and Safari see widgets that require less typing, less thinking about what to input.

I posted my CGI contact library on Launchpad for anyone who finds they need to work with historical technology.

Karma means action

I not only hack on Launchpad, I use it everyday for my personal projects and for the 1100+ projects I maintain as a registry administrator. I see hundreds of pages each week where my first question is “what has this user or project done recently”? Launchpad cannot easily tell me that, and what it does say requires interpretation. I am very disappointed. I think the most important information I need to see on Launchpad pages is an activity log.  I want to see something like a wall or stream presentation to understand how a person contributes to projects, what kinds of contributions are made, and is a project vital or dormant? My disappointment is compounded by Launchpad’s karma mechanism. I happen to know that “karma” is a Sanskrit word meaning “action”, which is not how Launchpad users or engineers interpret it.

I not writing an argument to fix Launchpad’s karma. It is fundamentally corrupt. Discussions about it become bike shed arguments. I like the name “karma” because I know it’s essential meaning, and that is all that I want to preserve.

For your edification, the value attributed to your action in Launchpad was arbitrarily set by an engineer, then a mechanism “balanced” the number against values in rarely used features.  These rules were created to in an effort to bring fairness to actions. We know that some actions help more people than other actions, but what is happening is that someone was awarded a tremendous number of points for some action that will never help someone else. For example, You can work for a year to build and release an app to earn 10 points, then Launchpad slaps you in the face when I register a blueprint that will never be implemented…awarding me with 300 points. Launchpad is misinforming you and everyone else about the value of your contributions. The numbers will always be subjective. Stop reading those karma numbers, stop trying to raise them; you will not win anything for having a high score.

  • I want to stop recording values for action, at the very least, never show them.
  • I want to stop expending valuable CPU time balancing karma.
  • I want to stop expiring karma.

Once we stop talking about value and fairness, we are free to add new kinds of actions that we want Launchpad to record. I hope to know that someone has registered a project, set the branch used as development focus, added a recipe to build it, and made an official release.

  • I want to see a listing of all the things I register or change in Launchpad.
  • I want to see a list of actions that someone has done today, this week, this month, this year, and maybe even last year.
  • I want to filter the actions by to specific categories that pertain to bugs, code, or planning.
  • I want see a link to the thing the action was about.


Misadventures with gnome Javascript

I recently updated pocket-lint to require gjs instead of seed because the latter has been 100% broken for 6 weeks. The best thing I can say about this experience is that I am very happy there are two competing implementations of GObject Introspection bindings for JavaScript. I am disappointed that the two implementations are not 100% compatible. Most of my changes to pocket-lint were to hide the deficiencies of gjc.

There are small but important differences between gjc and seed that developers will want to be mindful of. Gjs is older, based on Spider Monkey, and servers a simple need: JavaScript is the most common development language, and GNOME should support it. Seed is newer, based on Webkit, and serves subtly different need: I know JavaScript and I want to develop GNOME applications. Gjs works though you might not know it given the lack of documentation, and you might be disappointed to see that it recommit’s JavaScript’s original sin of namespace pollution. Seed is well documented and its extensions are in a separate namespace. Seed’s documentation is 99% compatible with gjs, so I can forgive the oversight. I learned missing crucial 1% of gjs by reading the C source. I was appalled to discover that gjs creates print, log, and argv functions in the global namespace. Seed, being an implementation for developers who really use JS, place the extensions in the Seed object.

I want to use seed, but given that it is broken in Ubuntu Oneiric, I decided to support gjs. I chose to check for the existence of the Seed object, and construct one from gjs when it is not present. The namespace is still polluted. The interpreters have different command lines, though they are similar enough for my purposes.

I think the GNOME community could do better by updating the gjs and seed to share the same command line, and add extensions to a common namespace, such as System. Thus an app that wants to call System.print() will not care about which interpreter is used. This permits developer and distros to choose the backend of their choice. It also lets us change our minds.

PS. I know that some developers want to use gjs to use the JavaScript advances developed by the Mozilla community, but this is a fools pursuit. JS has been fragmented since the release of IE 3.0 in 1996. JS developers know they have to write for a common language, and use libs to provide extensions. I am very aware of the failure of ES4. I hope Mozilla can get its extensions into the official language.

Recovering Ubuntu after an OS X Lion upgrade

I updated my Macbook to OS X Lion over the weekend and had a nasty scare. I could not boot back to Ubuntu, nor could I see my Ubuntu partition. That is the moment where you think, “Is everything baked up? What will I loose?”. I remember that I switched from Evolution to Thunderbird last month; my email was lost. The truth is that everything was okay, and if this happens to you, you can fix this in a few minutes like I did.

I do not know what the OS X installer did. Maybe it resized the partitions. rEFIt did not report an issue. It verified that the the partition tables were synced. Grub did not know about Ubuntu though. I saw the grub prompt (grub>) instead of a message about the selected partition. I followed ubuntu mactel instructions to install Ubuntu, so I know Ubuntu should be on located on hd0,3. I typed:

grub> root (hd0,3)

grub> find /boot/grub/stage1

Find will report if it finds the boot information. If it does not find stage1, then you can try an alternate disk and partition, such as root (hd1,1) or root (hd0,4). When you find stage1 you can configure grub to fix boot:

grub setup (hd0,3)

I restarted and Ubuntu booted correctly. No data was lost.

The reason that OS X could not see my Ubuntu partition was because MacFuse was compiled for 32bit. Lion is 64bit. I installed the 64bit version of MacFuse to see Ubuntu and my data.

Creating a signed release file with setup.py

I recently created https://launchpad.net/lp-release-manager-tools for some videos I am making about how to use Launchpad. One aspect of creating a release is to upload the source tarball and a detached gpg signature verifying it. This is somewhat ironic, since lp-release-manager-tools exists to automate repetitive tasks that release managers do in Launchpad. I really do not like creating the signature. I cannot remember how to do it. I need to read the instruction on the form to upload the tarball each time. So I added a feature to my example project that any project hat uses python distutils can copy to make the signature with the source tarball.

I subclassed the sdist command and added an extra step to create the detached signature of the tarball. I then register the new command as signed_dist. This is the content of my setup.py:

import subprocess

from distutils.core import setup
from distutils.command.sdist import sdist

class SignedSDistCommand(sdist):
    """Sign the source archive with a detached signature."""

    description = "Sign the source archive after it is generated."

    def run(self):
        gpg_args = [
            'gpg', '--armor', '--sign', '--detach-sig', self.archive_files[0]]
        gpg = subprocess.Popen(
            gpg_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

    description="Launchpad release manager API scripts.",
    maintainer="Curtis C. Hovey",
        'signed_sdist': SignedSDistCommand,

A Practical Guide to Bug Triage

Or: “Why I don’t classify bugs as medium”

The process of triaging issues (bugs, features, and tasks) has one crucial principle: Prioritise the work according to need and certainty.

Work is prioritised because there are not enough engineers to do all the work. Some features will never be completed, some bugs will never be fixed. Triage determines which bugs can and will be fixed, which features can and will be implemented. Need is generally understood, when planning work, but certainty is not, and that often leads to wasted work and unmet expectations.

By need, I mean a measure of severity. What percentage of users does the issue affect, and how severely does it impede them from completing their task.

By certainty, I mean a measure of how certain the engineers are that they can address the issue. Time is also a factor in this measure, the longer an issue takes to address, the more likely that the conditions that were first judged will change.

The act of triage is separating work into groups that are being worked on now, next and last. There can only be as many “now” bugs or features as there are engineers. The number of “next” work is limited to the velocity of the engineers and how infrequently plans change. The bugs that are last will probably never be addressed, the last features may never be started.

The corollary to this rule is that there are a finite number of bugs or features in the first two groups. There cannot be more work in these groups than there are engineers to do for the given period of time; otherwise the engineers, businesses and users are being misinformed about when issues will be addressed.

An Example

Consider there is one engineer and two bugs. He can only work one bug at a time. One bug is more important than the other. The risk is that he may not be able to fix one of the bugs before users are disappointed and abandon the application. He risks disappointing all users if he does not fix either bug because he choose the one with the most need over the one he was certain he could address.

If he does not know how to fix the bug with the most need, or that the fix takes a long time, he is wasting time he could have spent fixing the bug with more certainty. The only way he can address the bug with the most need is to employ a hack to reduce the need, to meet the expectations of some users. The hack is also used to gain time to understand the problem, thus increase certainty.

Only Assign Work that You Are Committing to do in the Near Future

When a work is assigned to an engineer, he is committing to complete the work in the near future. What the “near future” means is different for each project. I suggest 3 releases is the “near future”, because when work is planned, the engineer is thinking about now, next, and last. For some projects this period might be 6 weeks, for others, 6 months.

I prefer to plan for the current release, and the next one. As work is reprioritised, it may be rescheduled to the third release. I do not think it is wise to plan a bug or feature to be completed in the third releases because if it slips to the fourth or fifth released, I doubt the it was correctly prioritized as high.

Any high work that is assigned to a engineer for more than 3 releases was not high. If it were, the work would have been reassigned to someone who could complete it in the scheduled time. Any other work that is assigned for more than 1 release is also misprioritised. You are lying to yourself, and the the project’s users, when you assign work that you are not committing to fixing.

Practical Classifications of Importance

Work is often classified in relative terms. It is better to classify work according to how it are managed to convey when and under what terms the bug will be fixed or a feature will be complete. There are three priorities that work can be classified as:

The bug dramatically impairs users. Users may lose their data. Users cannot complete crucial tasks. The feature is needed to encourage adoption or prevent abandonment of the project.

Synonyms: required, essential, now, must do

The work is immediately assigned to a engineer. It is his top priority to fix. Team members help the engineer to plan and do the work. The work is released as soon as it is deployable; in the case of a bug, it is released outside of the release schedule.
The bug prevents users from completing their tasks. The feature provides new kinds of tasks or new ways of completing tasks.

Synonyms: expected, next, can do, should do

The work is assigned to a engineer to be completed in the next 3 releases. The engineer may choose to do other work if he believes it is within the scope of the high priority work.
The bug is inconvenience for many users. The feature provides new ways of completing tasks.

Synonyms: preferred

The work is not scheduled, though it is intended to be completed. When the work is assigned, it may also be scheduled, but there is no commitment to complete it for the stated release. The engineer may choose to postpone the work in favour of more important work.
The bug is an inconvenience to users, but it does not prevent them from completing their tasks. The feature is a convenience to users.

Synonyms: optional, last, may do

The engineer may assign the work to himself while working on a high priority work because the high work provides an opportunity to complete the low priority work at less cost. If the low work in any way jeopardises the high priority work, the low work is unassigned. The engineer is thus certain that the work can be fixed quickly and without difficulty. A corollary to this rule is that low work that is assigned to a engineer must be “in progress” or “fixed” states.

The Problem with “Medium”

It might be argued that when the engineer has an opportunity to fix a low or a medium bug, he must choose the medium one. This rules does not define a practical distinction between medium and low. There is no commitment to fix the medium bug; it will not be scheduled for fixing. A engineer chooses to undertake a low bug because he sees an opportunity to fix it while working in the affected code. The engineer is choosing to do unscheduled work because he is certain it does not jeopardise his scheduled work. The engineer might see an opportunity to fix a medium and a low bug at the same time, but that is unlikely.

It can also be argued that ‘critical’ is ‘high’ and that ‘high’ is ‘medium’. True, that is a matter of semantics. The crux of the issue is that there are three practical classifications of work. The words chosen to describe the classifications could use the tofu scale of hard, firm, and soft. People who are unfamiliar with triage will appreciate names that convey the kind of attention the issue will receive.

Some teams with a large number of bugs prefer to keep a pool of medium work from which releases are planned. Items in the pool may be escalated to high if it is perceived that once work is started, there should be a commitment to complete it as scheduled. This work is different from low work because the work makes a substantial improvement to the application, but like low, there is no commitment when the work will be completed. It can be argued that work starts on medium bugs and features because of changes to other priorities, certainties, or the number of users it affects.

Consequences of Misprioritised Work

Stakeholders often use reports that list the prioritised work for a release and for each engineer. When work is misclassified there are two commonly observed consequences: a decreased in certainty, and a decrease in communication.

In the first consequence, the engineer’s effort may be wasted; there are issues that have more need and certainty. Engineers, and other stakeholders, are often tempted to complete the misdirected work after the misclassification is discovered because it is assumed that it is better to always deliver something finished than nothing at all. This is a risky choice, because it jeopardises work in future releases. By working on less important work, the engineer is decreasing the certainty of the more important work.

The second consequence is that the engineer ignores the list and he works on issues according to some other source, such as the opinion of another stakeholder. While the engineer is working on the correct issue, it is unclear to other parties what work is going on and when will it be completed. Users may abandon the project in frustration. Planners cannot coordinate all the stakeholders.

The first consequence is possibly a failure to do re-prioritisation during the triage process, but second consequence is a total failure in the triage process. Why would anyone do triage if the prioritisation will be ignored? How can work be coordinated if the work is unknown to all stakeholders? Why would users trust a project if it does not do what it says it will do?

Work must be reprioritised during the triage process to ensure that engineers are working on the issues with the most need and certainty. Engineers must work from the list or prioritised issues.

Indicators of Misprioritised Work

The rules of practical classification provide tests for misprioritised bugs, features, or tasks.

  • The work is critical, but it is not assigned and targeted for release.
  • The work prioritised as high, but it is not assigned and for a release.
  • The work is high, but have not been worked on in 3 releases.
  • The work is low and unassigned, yet it is targeted for a release.
  • The work is low and assigned, but the engineer is not working on it.
  • The work is considered to be triaged, but it’s priority is not critical, high, or low.
  • An engineer is assigned more work than he can accomplish in 3 releases, and it cannot be reassigned.

Launchpad font-size broken by design

I looked at Launchpad bug #523189 today. This bug cannot be fixed until Launchpad abandoned YUI-Font rules — percentages have unpredictable results when pages are constructed from fragment. Canonical own Web guidelines specify the use of pixels.

Launchpad uses YUI-Font to normaize font sizes across browser and OSes. It stipulates that all font sizes must be expressed in specific precentages to get the expected point size. This is difficult to use because browsers know that percentages are relative; nesting classes have surprising results.

The following text uses nesting with the same percentages that Launchpad uses.

An example of broken font-sizes in Launchpad

An example of broken font-sizes in Launchpad

Launchpd pages are constructed from many html fragments. The fragments are intended to be usable in many places on a page and display the the same way. Launchpad cannot use percentages for font-size.

Encouraging contribution on the project page

I met with Vish at UDS-N to discuss encouraging contributions to the One Hundred Paper Cuts project. The issues he raised demonstrate that the page design is not meeting the requirements we set in the Launchpad 3.0 UI designs. You will see a common layout in Launchpad pages where a wide narrative block is above two blocks.

Who, what, where, when, and hows of a project

The narrative blocks on a project page (and any Launchpad page using the same layout) must explain what the you are seeing and why it exists. This information is entirely dependant on the project owner.  One Hundred Paper Cuts does this very well. I can read that the project chooses 100 small bugs that can be fixed to improve the common Ubuntu user experience. The project summary says everything in one sentence. The projects description elaborates and explains the value.

The left block below the narrative provides information about who works with the project, and where is the code for the project. Some projects have information about the organisation that the project belongs too. In the case of One Hundred Paper Cuts, the information about “where” is missing and there is no way for Vish to provide it. This project does not have code, it organises work to fix the code in other projects. This is a legitimate use case. Launchpad does not require projects to have source code, but it does not let project owners state what it does as an alternative. I do not know how to solve this.

I would like to tell contributors that this project is affiliated with Ubuntu and User Experience, but Launchpad does not have a concept of project affiliation or tags. I would like to see similar projects that I could contribute to. There are no plans to provide this feature, but we are discussing what needs to be done to fix project groups which has overlapping issues. We may have an opportunity to build this feature next year.

The right block under the narrative is intended to be a call to action. Every page that uses this layout should using this block to encourage users to contribute. For distro series, this block shows the packages that need upstream information. For projects, this should summarise the planned work and what needs to be done. I see a fragment of the series and milestone time line, but it does not tell me what is being done.  The milestones names are not informative. The name implies that the milestones are a sequence, but the 10 milestones are worked concurrently. One Hundred Paper Cuts uses feature-directed milestones. Launchpad supports this work pattern, but the time line does not describe it. Vish could rename the milestone to reveal the theme of the feature, eg rename maverick-round-10-sc-metadata to software-centre-metadata.

Fixing the name is easy, but the information about the work will still not appear on this page. The project index page used to show a summary of the active milestones. I have pondered adding the current milestone to the page so that contributors can see what they can do right now…but how do I show 10 concurrent milestones? Pages that work with milestones are prone to timeouts. I cannot consider restoring milestone information until we solve the long python computation times needs to summarise them.

We can fix some of issues that the project index page has in the next few months, but I think some larger feature and design work is needed to really make the page work for all projects.

Launchpad Answers at UDS-n

While attending UDS-n, I was invited to two separate and contradictory conversations about Launchpad Answers.

Jorge Castro is considering Ask Ubuntu as the official Ubuntu service for managing user questions. It is a nice service. The question refining and member reputation features are compelling. I think there are two changes that need to happen to make this happen:

  1. Launchpad should let project register an external support service. I already have plans do this this later this month. Projects will be able to specify the URL of a site or email address of a list where support can be found. The external service can be used with Launchpad Answers, or by itself. This will permit communities to register the service they are already using, or allow end-users to choose the service that meets their needs.
  2. The Get help online page accessed by Ubuntu desktop applications must be updated to point users to the service the Ubuntu community chooses.

David Planella lead a discussion about internationalising Launchpad Answers. This is a feature we have long wanted to do, but it has never been a priority. This certainly can be done with the community’s help. While examining how users discover Launchpad Answers, we saw that the Get help online page accessed from Ubuntu desktop applications is a complete failure for non-English speaking users. The general steps to fix the non-English-speaker’s experience are:

  1. Automate POT extraction for code and templates.
  2. Add support to localise pages based on your preferred language or browser languages.
  3. Mark the translatable messages in the page templates, and this may require restructuring the information.
  4. Replace the ugly plural hacks in the view code–Zope markup does not support plurals.
  5. Enable translations for the Launchpad project.

Both David’s and George’s intentions are contradictory. The Ubuntu community needs to make a final decision regarding the future of community support before we can proceed. Stack Exchange does not support localisation either, and they do not have plans to support it.  We often talk about replace karma, no one will argue a case to support it, but replacing it is not a priority. Launchpad has an incomplete feature called standing that is like reputation; I am consider removing it because I do not like to maintain unused code.