--- a/ForgeTracker/forgetracker/tracker_main.py
+++ b/ForgeTracker/forgetracker/tracker_main.py
@@ -12,6 +12,8 @@
 from pylons import g, c, request
 from formencode import validators
 from pymongo.bson import ObjectId
+
+from ming.orm import session
 
 # Pyforge-specific imports
 from pyforge.app import Application, ConfigOption, SitemapEntry, DefaultAdminController
@@ -85,7 +87,15 @@
         if len(search_bins):
             links = links + search_bins
         if ticket:
-            links.append(SitemapEntry('Subtasks', className="todo"))
+            if ticket.super_id:
+                links.append(SitemapEntry('Supertask'))
+                super = model.Ticket.query.get(_id=ticket.super_id, app_config_id=c.app.config._id)
+                links.append(SitemapEntry('Ticket {0}'.format(super.ticket_num), super.url()))
+            links.append(SitemapEntry('Subtasks'))
+            for sub_id in ticket.sub_ids or []:
+                sub = model.Ticket.query.get(_id=sub_id, app_config_id=c.app.config._id)
+                links.append(SitemapEntry('Ticket {0}'.format(sub.ticket_num), sub.url()))
+            links.append(SitemapEntry('Create New Subtask', '{0}new/?super_id={1}'.format(self.config.url(), ticket._id)))
         links.append(SitemapEntry('Ticket Help', '.', className="todo"))
         links.append(SitemapEntry('Markdown Syntax', '.', className="todo"))
         links.append(SitemapEntry('Auditors', '.', className="todo"))
@@ -192,11 +202,13 @@
 
     @with_trailing_slash
     @expose('forgetracker.templates.new_ticket')
-    def new(self, **kw):
+    def new(self, super_id=None, **kw):
         require(has_artifact_access('write'))
         tmpl_context.form = ticket_form
         globals = model.Globals.query.get(app_config_id=c.app.config._id)
-        return dict(modelname='Ticket', page='New Ticket', globals=globals)
+        return dict(action=c.app.config.url()+'save_ticket',
+                    super_id=super_id,
+                    globals=globals)
 
     @expose('forgetracker.templates.not_found')
     def not_found(self, **kw):
@@ -244,7 +256,7 @@
     def save_ticket(self, ticket_num, tags, tags_old=None, **post_data):
         require(has_artifact_access('write'))
         if request.method != 'POST':
-            raise Exception('save_new must be a POST request')
+            raise Exception('save_ticket must be a POST request')
         globals = model.Globals.query.get(app_config_id=c.app.config._id)
         if ticket_num:
             ticket = model.Ticket.query.get(app_config_id=c.app.config._id,
@@ -266,15 +278,29 @@
             post_data['ticket_num'] = globals.last_ticket_num
             # FIX ME
 
-        custom_fields = {}
-        for field in globals.custom_fields:
-            custom_fields[field.name] = True
-        for k,v in post_data.iteritems():
-            if k in custom_fields:
+        custom_sums = set()
+        other_custom_fields = set()
+        for cf in globals.custom_fields or []:
+            (custom_sums if cf.type=='sum' else other_custom_fields).add(cf.name)
+        for k, v in post_data.iteritems():
+            if k in custom_sums:
+                # sums must be coerced to numeric type
+                try:
+                    ticket.custom_fields[k] = float(v)
+                except ValueError:
+                    ticket.custom_fields[k] = 0
+            elif k in other_custom_fields:
+                # strings are good enough for any other custom fields
                 ticket.custom_fields[k] = v
-            else:
+            elif k != 'super_id':
+                # if it's not a custom field, set it right on the ticket (but don't overwrite super_id)
                 setattr(ticket, k, v)
         ticket.commit()
+        # flush so we can participate in a subticket search (if any)
+        session(ticket).flush()
+        super_id = post_data.get('super_id')
+        if super_id:
+            ticket.set_as_subticket_of(ObjectId(super_id))
         redirect(str(ticket.ticket_num)+'/')
 
 
@@ -350,10 +376,19 @@
         tag_artifact(self.ticket, c.user, tags)
 
         globals = model.Globals.query.get(app_config_id=c.app.config._id)
-        if globals.custom_fields:
-            for field in globals.custom_fields:
-                self.ticket.custom_fields[field.name] = post_data[field.name]
+        any_sums = False
+        for cf in globals.custom_fields or []:
+            value = post_data[cf.name]
+            if cf.type == 'sum':
+                any_sums = True
+                try:
+                    value = float(value)
+                except ValueError:
+                    value = 0
+            self.ticket.custom_fields[cf.name] = value
         self.ticket.commit()
+        if any_sums:
+            self.ticket.dirty_sums()
         redirect('edit/')
 
     @expose()