Summary
Expose the resolved source directory of a workflow definition to steps, enabling workflows to reference sibling files (extension manifests, adapter scripts, etc.) without requiring the user to pass the path redundantly.
Motivation
As discussed in #3445, workflows loaded from a file path (specify workflow run ~/dev/my-project/setup.yml) have no way to discover where their own YAML file lives. This forces users to pass the source directory twice:
SPEX_SOURCE=~/dev/my-project specify workflow run ~/dev/my-project/setup.yml
WorkflowDefinition.source_path is already captured when loading from a file, but it is never propagated to steps.
Proposed solution
-
Template expression: {{ context.workflow_dir }} - the parent directory of the workflow definition file, available in all expression contexts (step configs, conditions, etc.)
-
Environment variable: SPECKIT_WORKFLOW_DIR - set automatically for shell steps, giving shell commands direct access without template interpolation.
-
Value semantics:
- For file-loaded workflows: parent directory of the source YAML file
- For installed-by-ID workflows: the installation directory (
.specify/workflows/<id>/)
- For string-loaded workflows:
None/empty (no source path available)
- On resume: the original source directory is preserved (persisted alongside the workflow copy)
Edge cases
- Resume: The definition is reloaded from
.specify/workflows/runs/<run_id>/workflow.yml, so the persisted copy's path differs from the original. The original workflow_dir must be persisted in state so resume restores the correct value.
- String-loaded workflows:
source_path is None; context.workflow_dir should be empty string or None, and SPECKIT_WORKFLOW_DIR should not be set.
References
Summary
Expose the resolved source directory of a workflow definition to steps, enabling workflows to reference sibling files (extension manifests, adapter scripts, etc.) without requiring the user to pass the path redundantly.
Motivation
As discussed in #3445, workflows loaded from a file path (
specify workflow run ~/dev/my-project/setup.yml) have no way to discover where their own YAML file lives. This forces users to pass the source directory twice:WorkflowDefinition.source_pathis already captured when loading from a file, but it is never propagated to steps.Proposed solution
Template expression:
{{ context.workflow_dir }}- the parent directory of the workflow definition file, available in all expression contexts (step configs, conditions, etc.)Environment variable:
SPECKIT_WORKFLOW_DIR- set automatically for shell steps, giving shell commands direct access without template interpolation.Value semantics:
.specify/workflows/<id>/)None/empty (no source path available)Edge cases
.specify/workflows/runs/<run_id>/workflow.yml, so the persisted copy's path differs from the original. The originalworkflow_dirmust be persisted in state so resume restores the correct value.source_pathisNone;context.workflow_dirshould be empty string orNone, andSPECKIT_WORKFLOW_DIRshould not be set.References