Slot tasks are registered but not decomposed by compound task decomposers
- Dominant language
- TypeScript
- Stars
- 3
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
## Summary
In `htn-ai@1.2.1`, `DomainBuilder.slot()` and `Domain.trySetSlotDomain()` expose a slot mechanism, but slot children are not decomposed by the built-in compound task decomposers.
This makes a slot unusable as a normal decomposition child in `select`, `sequence`, or `utility_select` task trees.
I verified this against the published npm package `htn-ai@1.2.1` with gitHead `f204f60e6a4ea54e55bb71c3e2122a3bfabc3dbf`, which resolves in this repository.
## Evidence from source
The slot API appears to be wired into the domain structure:
- `DomainBuilder.slot(slotId)` creates a `Slot` and adds it to the current compound task.
- `Domain.add()` accepts `Slot`, registers it in `this.slots`, and sets its parent.
- `Domain.trySetSlotDomain(slotId, domain)` calls `slot.setSubtask(domain.Root)`.
- `Slot.decompose()` delegates to the configured subtask.
However, the decomposition paths do not invoke `Slot.decompose()`:
- `selectorTask.ts` handles `CompoundTask` and `PrimitiveTask`, then has `// TODO: Add support for slots`.
- `sequenceTask.ts` handles `CompoundTask`, `PrimitiveTask`, and `PausePlanTask`, but not `Slot`.
- `utilitySelectorTask.ts` handles `CompoundTask` and `PrimitiveTask`; unsupported child types return failed.
So a slot can be added and populated, but it is not executed by the normal planner decomposition flow.
## Expected behavior
A `Slot` child should behave like its configured subtask during decomposition:
- If `slot.isValid(context)` is false, it should fail like any invalid child.
- If valid, the compound decomposer should call `slot.decompose(context, startIndex)` or an equivalent path.
- This should work consistently for `select`, `sequence`, and `utility_select` parents.
## Actual behavior
Slot children are not decomposed:
- `select` can report success without actually expanding the slot, because it does not handle `Slot` after the primitive branch.
- `sequence` does not include a `Slot` branch.
- `utility_select` treats unsupported child types as failed.
## Why this matters
The public API suggests slots can be used as dynamic subtrees, but the planner cannot currently use them as regular children. Users trying to build modular HTN domains with dynamic method/domain insertion need to avoid slots and instead rebuild the domain or splice concrete compound tasks manually.
## Possible fix
Add explicit `Slot` handling to the compound task decomposers. For example, each decomposer should treat a valid `Slot` similarly to a `CompoundTask`, delegating to its `decompose()` result and preserving MTR / plan behavior consistently with the surrounding task type.
For `utility_select`, the slot likely also needs a way to expose or delegate utility score from the configured subtask, instead of being treated as an unsupported child type.
If slots are not intended to be decomposition children yet, the API/docs should probably mark them as incomplete or experimental.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by reading selectorTask.ts, sequenceTask.ts, and utilitySelectorTask.ts alongside Slot.decompose() and the slot registration paths described in the issue. Trace how CompoundTask children are decomposed, then verify that valid and invalid Slot children behave consistently in select, sequence, and utility_select without breaking MTR or plan behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- ai
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100