if not modules then modules = { } end modules ['node-pro'] = {
    version   = 1.001,
    comment   = "companion to node-ini.mkiv",
    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files"
}

local trace_callbacks  = false  trackers  .register("nodes.callbacks",        function(v) trace_callbacks  = v end)
local force_processors = false  directives.register("nodes.processors.force", function(v) force_processors = v end)

local report_nodes = logs.reporter("nodes","processors")

local nodes        = nodes
local tasks        = nodes.tasks
local nuts         = nodes.nuts

nodes.processors   = nodes.processors or { }
local processors   = nodes.processors

local tasks        = nodes.tasks

local countnodes   = nuts.countall

do

    local function reconstruct(head)
        return ",stream : " .. nodes.listtoutf(head,"",false,nil,true)
    end

    local before = nil
    local count  = 0
    local show   = false

    function processors.trace_glyph_run_b(head,groupcode)
        count  = count + 1
        before = countnodes(head)
    end

    function processors.trace_glyph_run_a(head,groupcode)
        report_nodes("processors: run %i, group %a, # before %a, # after %s%s",
            count,groupcode,before,countnodes(head),
            show and reconstruct(head) or ""
        )
        before = false
    end

    local prependaction = tasks.prependaction
    local appendaction  = tasks.appendaction
    local enableaction  = tasks.enableaction
    local disableaction = tasks.disableaction

    trackers.register("nodes.callbacks", function(v)
        if not v then
            disableaction("processors","nodes.processors.trace_glyph_run_b")
            disableaction("processors","nodes.processors.trace_glyph_run_a")
        elseif before == nil then
            prependaction("processors","before","nodes.processors.trace_glyph_run_b",nil,"nonut","enabled")
            appendaction ("processors","after", "nodes.processors.trace_glyph_run_a",nil,"nonut","enabled")
            before = false
        else
            enableaction("processors","nodes.processors.trace_glyph_run_b")
            enableaction("processors","nodes.processors.trace_glyph_run_a")
            show = v == "detail"
        end
    end)

end

do

    local glyph_run_callback      = tasks.actions("processors")
    local pre_linebreak_callback  = tasks.actions("paragraphs")
    local post_linebreak_callback = tasks.actions("finalizers")

    callbacks.register {
        name    = "glyph_run",
        action  = glyph_run_callback,
        comment = "glyph processing",
        frozen  = true,
    }

    callbacks.register {
        name    = "pre_linebreak",
        action  = pre_linebreak_callback,
        comment = "horizontal manipulations (before par break)",
        frozen  = true,
    }

    callbacks.register {
        name    = "post_linebreak",
        action  = post_linebreak_callback,
        comment = "horizontal manipulations (after par break)",
        frozen  = true,
    }

    local hpack = nuts.hpack

    function nuts.fullhpack(head,...)
        return hpack(glyph_run_callback(head),...)
    end

    local tonut  = nodes.tonut
    local tonode = nodes.tonode

    function nodes.fullhpack(head,...)
        return tonode(hpack(glyph_run_callback(tonut(head)),...))
    end

end

do

    -- This was the "contributers" callback but we changed the interface and now have
    -- three dedicated ones.

    local getlist    = nuts.getlist
    local setlist    = nuts.setlist
    local getsubtype = nuts.getsubtype

    local linelist_code <const> = nodes.listcodes.line

    local lineactions    = tasks.actions("contributers") -- we keep the old name
 -- local adjustactions  = tasks.actions("adjusters")
 -- local migrateactions = tasks.actions("migrators")

    -- todo: pre_append_line or just get rid of it

    local function append_line_callback(head,tail)
     -- if tail then
            -- here we don't return something, we operate on the line (content)
            local list = getlist(tail)
            if list then
                local result = lineactions(list,where,tail) -- tail is parent of list
                if result and result ~= list then
                    setlist(tail,result)
                end
            end
     -- end
    end

    callbacks.register {
        name    = "append_line",
        action  = append_line_callback,
        comment = "things done with lines",
        frozen  = true,
    }

 -- local function append_adjust_callback(head,tail,where,index)
 --  -- if tail then
 --         return adjustactions(head,where,tail,index)
 --  -- end
 -- end

    local append_adjust_callback = tasks.actions("adjusters")

    callbacks.register {
        name    = "append_adjust",
        action  = append_adjust_callback,
        comment = "things done with vertical adjusts",
        frozen  = true,
    }

 -- local function append_migrate_callback(head,tail,where)
 --  -- if tail then
 --         return migrateactions(head,where,tail)
 --  -- end
 -- end

    local append_migrate_callback = tasks.actions("migrators")

    callbacks.register {
        name    = "append_migrate",
        action  = append_migrate_callback,
        comment = "things done with migrated material",
        frozen  = true,
    }

end

do

    local actions = tasks.actions("alignments")

    local function alignment_callback(head,where,callback,attr,preamble)
        if callback then
            actions(head,where,callback,attr,preamble)
        end
    end

    callbacks.register {
        name    = "alignment",
        action  = alignment_callback,
        comment = "things done with alignments",
        frozen  = true,
    }

end

do

    -- dummy, not to be used, we have no need to add more overhead

    callbacks.register {
        name     = "hpack",
        action   = false,
        comment  = "hlist processing (not used, replaced)",
        frozen   = true,
        disabled = true,
    }

    callbacks.register {
        name     = "append_to_vlist",
        action   = false,
        comment  = "vlist processing (not used, replaced)",
        frozen   = true,
        disabled = true,
    }

end
