Dynamically accessing "parent" group of a record

For large documents, I’m creating a companion “reading notes” file in omnioutliner.
I’m trying to automate the process as follows:

  • select the document in DTPO
  • type a hot key which activates a script (through a KM Macro) to :
    • fetch a template oo file at a fixed location in my document folder
    • save the oo file in DTPO with the same name as the main file and IN THE SAME GROUP as the orignal file
    • open both files side to side.

I’m using the “open two files” script as a starting point.

I’m stuck with identifying the GROUP to which my current selected record belongs. I wanted to do this :

tell application id "DNtp"
	set curRec to (item 1 of (selection as list))
	set curUuid to (kind of curRec)
	set curParent to (parent of curRec)
	set dest to curParent
	set newRec to (create record with {name:"test", content:"my test", type:txt}) in dest
end tell[

but it creates the record in my Global Inbox (which is the default new record creation location)
Obviously, I don't understand how the "parent" property works ....
Any ideas ?

Each record can have multiple parents, e.g. if it’s tagged or replicated. Therefore you have to use e.g. “parent 1 of curRec”.

A JavaScript for Automation route to the primary ancestral path of the first selected item:

(() => {

    // Primary ancestral path of selected DEVONthink item

    const main = () => {
        const xs = Application('DEVONthink Pro').selection();
        return 0 < xs.length ? (
                    x => x.name(), // E.G. as name strings
        ) : '';

    // DEVONthink -----------------------------------------

    // primaryPath :: (Record -> a) -> Record -> [a]
    const primaryPath = (f, item) => {
        const go = x => {
            const ps = x.parents() || [];
            return 0 < ps.length ? (
            ) : [];
        return go(item);

    // GENERIC --------------------------------------------

    // unlines :: [String] -> String
    const unlines = xs => xs.join('\n');

    // MAIN ---
    return main();

Or Applescript

on run
    tell application "DEVONthink Pro" to set xs to selection
    if xs ≠ {} then
        unlines(primaryPath(itemName, item 1 of xs))
    end if
end run

-- primaryPath :: (Record -> a) -> Record -> [a]
on primaryPath(f, x)
    script go
        property mf : mReturn(f)'s |λ|
        on |λ|(x)
            using terms from application "DEVONthink Pro"
                set ps to parents of x
            end using terms from
            if ps ≠ {} then
                go's |λ|(item 1 of ps) & mf(x)
            end if
        end |λ|
    end script
    go's |λ|(x)
end primaryPath

-- itemName :: DT Record -> String
on itemName(x)
    using terms from application "DEVONthink Pro"
        name of x
    end using terms from
end itemName

-- Lift 2nd class handler function into 1st class script wrapper 
-- mReturn :: First-class m => (a -> b) -> m (a -> b)
on mReturn(f)
    if class of f is script then
            property |λ| : f
        end script
    end if
end mReturn

-- unlines :: [String] -> String
on unlines(xs)
    set {dlm, my text item delimiters} to ¬
        {my text item delimiters, linefeed}
    set str to xs as text
    set my text item delimiters to dlm
end unlines

Thank you both for your answers - I’d solved my problem with a hack but I’m sure it’ll go quicker knowing how to manage parents.

Also, it’s opened a can of worms into JXA for me, of course - good thing I’m on vacation :slight_smile: