Summary
src/taskfile-include-mkdocs.yaml documents its override example with a relative path, while both of its tasks run in the caller's directory and activate the interpreter through a bare source. A consumer who copies the documented example gets a module that only works when task is invoked from the repository root, and fails everywhere else with a shell error that names nothing about the cause.
The module's own default is fine — ~/.venvs/docs is absolute, so it resolves identically from any directory. Only the documented override is affected, which makes this a documentation defect with a runtime consequence rather than a broken default.
Where it is
src/taskfile-include-mkdocs.yaml on develop:
- :17 — the usage comment shows
PYTHON_VENV_DIR_DOCS: .venv
- :35 and :45 —
start and build both declare dir: '{{.USER_WORKING_DIR}}', so they run in the directory task was invoked from, not in the consumer's root
- :39 and :47 — both activate through a bare
source {{.PYTHON_VENV_DIR_DOCS}}/bin/activate
A relative value therefore resolves against whatever directory the caller happened to be in.
Reproduction
Consumer Taskfile at a repository root with a project-local .venv, following the documented example:
includes:
mkdocs:
taskfile: "{{.TASK_COLLECTION_BASE}}/taskfile-include-mkdocs.yaml"
vars:
PYTHON_VENV_DIR_DOCS: .venv
task docs from the repository root: works.
task docs from any subdirectory: source .venv/bin/activate runs with the subdirectory as cwd, the file isn't there, and the task dies on a shell error that mentions neither the module, nor the variable, nor the override.
The trap in the obvious fix
Reaching for {{.TASKFILE_DIR}} to make the value absolute makes it worse, not better. Measured against Task 3.52.0, inside an includes: vars: block:
| Override |
Local include |
Remote include (how this collection is consumed) |
{{.TASKFILE_DIR}}/{{.VENV}} |
the included module's directory, not the consumer's |
empty string, so the value collapses to /.venv |
{{.ROOT_DIR}}/{{.VENV}} |
consumer's root |
consumer's root |
Both were checked from the repository root and from a subdirectory. So the remote shape — the one every consumer of this collection uses — turns a TASKFILE_DIR-based override into /.venv, which fails from every directory including the root. That is strictly worse than the relative form this issue is about, and it's the natural first attempt at a fix.
{{.ROOT_DIR}} resolved correctly in all four combinations. Its one limitation: it points at the parent when a parent Taskfile includes the consumer's, so a nested setup has to pass the path explicitly.
Suggested fix
Change the usage comment at :17 to show the absolute form, and say why in one line, so a consumer copying it doesn't have to rediscover the interaction with dir: '{{.USER_WORKING_DIR}}':
# includes:
# mkdocs:
# taskfile: "{{.TASK_COLLECTION_BASE}}/taskfile-include-mkdocs.yaml"
# vars:
# # Absolute: the tasks below run in the caller's directory, so a
# # relative value resolves against wherever `task` was invoked.
# PYTHON_VENV_DIR_DOCS: "{{.ROOT_DIR}}/.venv"
Fixing the documentation is enough; the tasks themselves don't need to change. Pinning the tasks' own dir: would be a separate, larger decision with its own consumer impact.
Why this is worth fixing upstream
nolte/claude-shared ships a reference consumer at spec/project/taskfile/templates/Taskfile.yml whose spec MUSTs every scaffolding artefact to adapt it. That template followed the documented example here and inherited the defect, which then had to be corrected downstream (nolte/claude-shared#549). The downstream fix makes one consumer robust; correcting the documented example here stops the next consumer from walking into it.
Related: #42, which established that the module's variables must be written in the default form for consumer overrides to arrive at all. This issue is about the value a consumer is told to pass, not about whether the override reaches the command.
Summary
src/taskfile-include-mkdocs.yamldocuments its override example with a relative path, while both of its tasks run in the caller's directory and activate the interpreter through a baresource. A consumer who copies the documented example gets a module that only works whentaskis invoked from the repository root, and fails everywhere else with a shell error that names nothing about the cause.The module's own default is fine —
~/.venvs/docsis absolute, so it resolves identically from any directory. Only the documented override is affected, which makes this a documentation defect with a runtime consequence rather than a broken default.Where it is
src/taskfile-include-mkdocs.yamlondevelop:PYTHON_VENV_DIR_DOCS: .venvstartandbuildboth declaredir: '{{.USER_WORKING_DIR}}', so they run in the directorytaskwas invoked from, not in the consumer's rootsource {{.PYTHON_VENV_DIR_DOCS}}/bin/activateA relative value therefore resolves against whatever directory the caller happened to be in.
Reproduction
Consumer Taskfile at a repository root with a project-local
.venv, following the documented example:task docsfrom the repository root: works.task docsfrom any subdirectory:source .venv/bin/activateruns with the subdirectory as cwd, the file isn't there, and the task dies on a shell error that mentions neither the module, nor the variable, nor the override.The trap in the obvious fix
Reaching for
{{.TASKFILE_DIR}}to make the value absolute makes it worse, not better. Measured against Task 3.52.0, inside anincludes:vars:block:{{.TASKFILE_DIR}}/{{.VENV}}/.venv{{.ROOT_DIR}}/{{.VENV}}Both were checked from the repository root and from a subdirectory. So the remote shape — the one every consumer of this collection uses — turns a
TASKFILE_DIR-based override into/.venv, which fails from every directory including the root. That is strictly worse than the relative form this issue is about, and it's the natural first attempt at a fix.{{.ROOT_DIR}}resolved correctly in all four combinations. Its one limitation: it points at the parent when a parent Taskfile includes the consumer's, so a nested setup has to pass the path explicitly.Suggested fix
Change the usage comment at :17 to show the absolute form, and say why in one line, so a consumer copying it doesn't have to rediscover the interaction with
dir: '{{.USER_WORKING_DIR}}':Fixing the documentation is enough; the tasks themselves don't need to change. Pinning the tasks' own
dir:would be a separate, larger decision with its own consumer impact.Why this is worth fixing upstream
nolte/claude-sharedships a reference consumer atspec/project/taskfile/templates/Taskfile.ymlwhose spec MUSTs every scaffolding artefact to adapt it. That template followed the documented example here and inherited the defect, which then had to be corrected downstream (nolte/claude-shared#549). The downstream fix makes one consumer robust; correcting the documented example here stops the next consumer from walking into it.Related: #42, which established that the module's variables must be written in the
defaultform for consumer overrides to arrive at all. This issue is about the value a consumer is told to pass, not about whether the override reaches the command.