Workflow Runtime Artifacts Reference¶
This reference defines the runtime-root, cleanup, and guard-point contracts used
by default-workflow, recovery flows, launchers, provenance logging, publish
helpers, and finalization helpers.
Updated: 2026-06-25
Contents¶
- Environment variables
- Runtime root resolution
- Runtime directory layout
- Known worktree-local artifacts
- Shell helper API
- Lifecycle integration
- Artifact Guard interaction
- Regression contract
Environment variables¶
| Variable | Direction | Meaning |
|---|---|---|
AMPLIHACK_RUNTIME_ROOT |
Read and propagated | Absolute directory for workflow-generated runtime files. |
AMPLIHACK_RECIPE_RUN_ID |
Set by amplihack recipe run |
Stable per-run ID used in default runtime-root paths and log correlation. |
XDG_RUNTIME_DIR |
Read | Preferred platform runtime base when AMPLIHACK_RUNTIME_ROOT is unset. |
TMPDIR |
Read indirectly | Host temporary directory preference for tools that create additional scratch output. |
AMPLIHACK_AGENT_BINARY |
Propagated | Active agent runtime for child agentic steps. |
AMPLIHACK_NONINTERACTIVE |
Propagated | Forces child workflow and helper processes into non-interactive mode. |
AMPLIHACK_RUNTIME_ROOT is treated only as a filesystem path. Recipes and shell
helpers quote it and never evaluate it as shell code.
The top-level workflow establishes AMPLIHACK_RUNTIME_ROOT once. Child
workflows, nested recipes, and agents inherit it unchanged; they must not run
runtime-root resolution again and create sibling roots.
Runtime root resolution¶
The shared resolver returns one runtime root for a workflow run.
| Priority | Source | Example |
|---|---|---|
| 1 | AMPLIHACK_RUNTIME_ROOT |
/var/tmp/amplihack-runtime/alice/run-123 |
| 2 | $XDG_RUNTIME_DIR/amplihack/runtime/<run-id> |
/run/user/1000/amplihack/runtime/550e8400-e29b-41d4-a716-446655440000 |
| 3 | /tmp/amplihack-runtime/<user>/<run-id> |
/tmp/amplihack-runtime/alice/550e8400-e29b-41d4-a716-446655440000 |
The resolver rejects empty paths, root paths, and paths that cannot be created.
Workflow-managed defaults are outside Git worktrees and are created with
restrictive owner-only permissions where the platform supports them. If a caller
explicitly sets AMPLIHACK_RUNTIME_ROOT, they are responsible for selecting a
private external path.
Runtime directory layout¶
The resolver creates these subdirectories before child workflows or agents run:
Launchers use the runtime root for generated launcher state. Provenance logging
uses the provenance/, logs/, metrics/, and reflection/ directories.
Recipe helpers may add run-scoped files under these directories, but must not
write generated runtime output into the task worktree.
Launcher context files used for active-agent routing belong under the runtime
root. <worktree>/.claude/runtime/launcher_context.json is legacy fallback
state only and must not be treated as canonical by new workflow code.
Process metadata for nested agents, workstreams, provider helper calls, and simulation runs is stored under the runtime root. Recipes use that metadata for scoped closure and finalization instead of relying on host-global process lists or stale PID-only records.
Known worktree-local artifacts¶
Only these worktree-local paths are classified as known workflow runtime artifacts:
| Repo-relative path | Owner | Cleanup behavior |
|---|---|---|
.claude/runtime |
legacy amplihack launcher and nested agent runtime state | Removed by workflow runtime preflight when present. |
worktrees |
reserved root for amplihack workflow-created nested scratch worktrees under a managed task worktree | Nested git worktrees are deregistered (git worktree remove --force + git worktree prune) and the directory is removed by workflow runtime preflight when present and not tracked source. A bare rm -rf is never sufficient: it leaves dangling worktree registrations behind (issue #808 — a regression of the #780/#755 local-leak fixes). |
The cleanup contract does not include .claude itself, .claude/settings.json,
source files, build output, dependency directories, logs outside the runtime
root, or arbitrary untracked files.
Root-level worktrees/ is reserved in amplihack-managed task worktrees. If a
repository intentionally tracks source under that path, the workflow must fail
closed and require a repository layout change instead of deleting it.
Shell helper API¶
The helper script lives at:
Source it from recipe shell steps or workflow helper scripts:
Helper path resolution¶
The helper is not required to live under the target repository. Recipe lifecycle
steps resolve workflow_runtime_artifacts.sh by checking these locations in
order and using the first that exists:
| Priority | Candidate | Purpose |
|---|---|---|
| 1 | $WORKFLOW_RUNTIME_ARTIFACT_HELPER |
Explicit override (publish/tool steps). |
| 2 | $AMPLIHACK_HOME/amplifier-bundle/tools/... |
Honor an explicit Amplihack home. |
| 3 | $REPO_PATH/amplifier-bundle/tools/... |
Target repo checkout that bundles the tools. |
| 4 | $(pwd)/amplifier-bundle/tools/... |
Active worktree that bundles the tools. |
| 5 | $HOME/.copilot/amplifier-bundle/tools/... |
Copilot-installed bundle. |
| 6 | $HOME/.amplihack/amplifier-bundle/tools/... |
Default installed Amplihack bundle. |
When AMPLIHACK_HOME is unset and the target repository does not vendor an
amplifier-bundle/ directory, the helper still resolves from the installed
~/.amplihack (or ~/.copilot) bundle. The step fails with a clear error only
when no candidate resolves. This prevents a successful implementation from being
reported as failed at checkpoint-after-implementation (issue #817).
cleanup_known_workflow_runtime_artifacts¶
Removes the known workflow runtime artifact paths if they exist. Missing known paths are a successful no-op. For each existing target, the helper:
- Requires a non-empty worktree path.
- Requires the path to resolve to a Git worktree.
- Resolves the worktree and existing target paths before deletion.
- Rejects tracked source paths, symlink escapes, and targets outside the worktree.
- Deletes only exact matches for
.claude/runtimeandworktreesunder the active worktree. - Fails non-zero if validation or deletion fails.
preflight_known_workflow_runtime_artifacts¶
Runs cleanup, then verifies that the known runtime artifact paths are absent. Use this function before guard-sensitive lifecycle operations.
Deterministic finalization cleanup (issue #808)¶
When a default-workflow run hits a denied force-push, its push-fallback path
could spray throwaway branches to the shared remote and leave nested worktrees
behind, with no finalization cleanup to remove them. The helper exposes a
deterministic, idempotent, fail-soft cleanup for that leak class. Every function
returns success even when individual git operations fail, so it is safe to
call from success and failure/early-exit paths (for example an EXIT trap). The
intended PR branch, any branch still checked out in a worktree, and the
protected base branches (main, master, develop) are never deleted.
record_run_created_branch¶
Tracks a run-created fallback/intermediate branch in a per-run manifest stored
under the shared git common dir
($(git rev-parse --git-common-dir)/amplihack/run-created-branches-<run-id>,
scoped by AMPLIHACK_RECIPE_RUN_ID so concurrent runs never consume each
other's entries). Deduplicated and idempotent. Whenever the workflow pushes a
branch other than the intended PR branch, it records it here so finalization
can delete it.
cleanup_run_created_branches¶
Deletes every manifest-tracked branch from the shared remote
(git push origin --delete) and locally (git branch -D), then consumes the
manifest. Preserves the intended/checked-out/protected branches.
cleanup_nested_worktrees¶
Removes every registered git worktree that lives under <repo>/worktrees/ with
git worktree remove --force and prunes dangling registrations with
git worktree prune. Operating on the per-task worktree, this only touches
worktrees nested inside it — never the task worktree itself, a sibling task
worktree, or the main worktree.
finalize_workflow_runtime_artifacts¶
Finalization entry point. It captures the branches of nested worktrees, removes
the nested worktrees, deletes those now-orphaned branches plus any
manifest-tracked fallback branches from the shared remote and locally, and then
runs the narrow runtime-artifact sweep. Call it with a dedicated per-task
worktree as <repo>: nested-worktree removal only touches worktrees/
children of that worktree, never the worktree itself, a sibling task worktree,
or the main worktree.
finalize_workflow_cleanup_entry¶
Recipe-facing entry point (invoked from workflow_agentic_finalization.sh
collect). It runs finalize_workflow_runtime_artifacts only when
worktree_path is a linked worktree whose canonical toplevel differs from the
repo root; otherwise it runs only the manifest-keyed branch cleanup (which never
removes a worktree). Deleted branches never include the intended PR branch, a
checked-out branch, or a protected/default branch.
Lifecycle integration¶
The bundled workflows and helper scripts call
preflight_known_workflow_runtime_artifacts before lifecycle operations that
would otherwise fail on workflow-owned leftovers.
| File | Required preflight points |
|---|---|
workflow-worktree.yaml |
Establish AMPLIHACK_RUNTIME_ROOT for the top-level managed task worktree and propagate it unchanged to child workflows. |
workflow-tdd.yaml |
Before checkpoint and broad staging. |
workflow-refactor-review.yaml |
Before checkpoint and broad staging. |
workflow-pr-review.yaml |
Before checkpoint and broad staging. |
workflow-publish.yaml |
Before dirty checks, publish staging, commit, push, and PR creation. |
workflow-finalize.yaml |
Before final status gates and final broad staging. The deterministic finalization cleanup runs inside workflow_agentic_finalization.sh collect (invoked unconditionally by collect-finalization-evidence) via finalize_workflow_cleanup_entry, deleting run-created fallback branches (remote + local) and removing nested worktrees before evidence is collected. |
workflow_publish_pr.sh |
Before dirty-worktree checks and broad staging. |
workflow_final_status.sh |
Before final clean-worktree validation. |
Any new recipe step that invokes git add -A, performs publication staging, or
requires a clean worktree must run the same preflight immediately before the
operation.
Artifact Guard interaction¶
Artifact Guard is still the authority for unexpected artifacts. It does not delete files and it is not weakened for workflow runtime isolation.
The order is:
isolate runtime output outside worktree
preflight known workflow runtime leftovers
run strict Artifact Guard or clean-worktree gate
stage, commit, publish, or finalize
If .claude/runtime or worktrees/ remains after preflight, the lifecycle step
fails visibly. If any unrelated artifact remains, Artifact Guard fails visibly.
Regression contract¶
Regression coverage for workflow runtime isolation verifies:
- Creating
.claude/runtimeunder a task worktree no longer breaks later checkpoint, staging, publish, or finalization gates because preflight removes the known workflow-owned path. - Creating
worktrees/under a task worktree no longer breaks later lifecycle gates because preflight removes the known workflow-owned path. - User-authored
.claudefiles, including.claude/settings.json, remain untouched. - Unrelated untracked files still fail strict guard behavior.
- Runtime-root resolution honors
AMPLIHACK_RUNTIME_ROOTand otherwise chooses an external default path. - Launcher state and provenance output are written under the shared runtime root contract.
- Child workflows inherit
AMPLIHACK_RUNTIME_ROOT,AMPLIHACK_AGENT_BINARY, and non-interactive settings without recomputing or leaking runtime state into the commit worktree. - Lifecycle steps resolve
workflow_runtime_artifacts.shfrom the installed~/.amplihack(or~/.copilot) bundle whenAMPLIHACK_HOMEis unset and the target repository has noamplifier-bundle/directory (issue #817). - Finalization deletes run-created fallback branches from the shared remote and locally, removes nested worktrees without leaving dangling worktree registrations, deletes the nested worktree's orphaned branch (remote + local), and always preserves the intended PR branch and protected base branches (issue #808). The cleanup is idempotent and never aborts the caller.