Skip to content

Troubleshooting

This chapter covers common issues and their solutions, organized by symptom.

Harness note. Symptoms and fixes below are written for Claude Code (hook filenames, settings.json blocks, compaction behaviour). The deterministic core — state, audit, the engine — behaves identically on every harness, but the shell-level surfaces differ: the other harnesses wire hooks and config their own way (see Running on other harnesses). Where a fix names a .claude/ path or a Claude mechanic, the equivalent lives in your harness's config dir.


Quick Fix Table

Symptom Quick Fix
No audit entries appearing Run aidlc doctor; for a copy install, also verify bun is on the hook PATH
I edited a file by hand; will the agent accept it? Yes: edit, then say done (or carry on). An edit to a finished stage is used as is but not re-approved; to have it approved, jump back with /aidlc --stage <name>, which reopens that stage and every stage after it. See Editing Files Yourself for each case
Claude hooks are restricted by policy Ask the Claude Code administrator to lift managed allowManagedHooksOnly; project settings cannot override it
Cursor: approvals are never recorded If the project is not in a git repository, run git init in it, then fully restart Cursor and trust the folder (see Cursor project outside a git repository)
Kiro IDE: deny fs_read matching ".kiro/" Run /aidlc --doctor; remove the .kiro/ rule from the ignore file it names (see Kiro IDE Read Denials)
Kiro IDE: AI-DLC's reviews and helpers do not run, the chat shows Approval needed in agent-aidlc-... panels, or /aidlc is handed to a Kiro workflow Kiro's Workflows feature is on. Ask the agent to turn it off, or run aidlc config trust --kiro-workflows off --yes, then Developer: Reload Window (see Kiro's Workflows feature)
Kiro IDE on Windows: command results end at an AI-DLC reply: line and steps take extra turns, or every command shows exit code -1 Kiro's terminal is Command Prompt. Ask the agent to set it to PowerShell, or run aidlc config trust --kiro-terminal powershell --yes, then restart Kiro (see Command Prompt as Kiro's terminal)
Kiro IDE: the agent cites "my memory" and suggests bypassing a check or running a hook by hand Ignore it and delete that Kiro memory (see Kiro memories carry old AI-DLC advice)
State file corrupted Run /aidlc --doctor, compare against state template
Stuck at approval gate Type your response; use /aidlc --stage <target> to jump past it
Kiro IDE: a build, test or probe command the agent ran shows Exit Code: -1 while AI-DLC's own commands work Kiro did not run it: it is waiting for you to allow it, or you declined it. Choose Allow (or Always allow) on Kiro's prompt, or tell the agent how to go on
Kiro IDE: your reply to an approval question is not seen, or commands come back with exit code -1 Choose Trust Folder & Continue when Kiro asks whether you trust this folder (or select Manage, then Trust, on the Restricted Mode banner), then run Developer: Reload Window from the Command Palette and say carry on; if your next message is still not recorded, /aidlc --doctor shows why. In Kiro CLI, quit and start kiro-cli again in the folder (see Kiro IDE hooks not running)
Kiro IDE: an approval says your answer was not recorded and names aidlc-record-human-turn under Agent Hooks, or the next AI-DLC step says an AI-DLC hook is switched off in Kiro's Agent Hooks You switched that hook off in the Agent Hooks panel; AI-DLC never turns it back on for you. Turn it back on there (see A Kiro hook switched off under Agent Hooks)
Kiro CLI (or a Kiro ACP client): every approval says no human reply has arrived, and restarting does not help The engine does not match the distribution: kiro needs Kiro CLI's v2 engine, kiro-ide needs v3 (see Kiro CLI hooks not running)
Context compacted mid-session Run /aidlc to resume from checkpoint
Audit log too large Leave it where it is: a long project's audit file is large by design, and the engine reads it to know what you approved and finished (see Audit Log Growing Too Large)
Hooks appear to hang Diagnose lock ownership with /aidlc --doctor; see Lock Files Left Behind
Statusline shows "ready" Check aidlc-state.md has a **Lifecycle Phase** field
Statusline not appearing It shows only once you turn it on: /aidlc --statusline on (Claude Code and Codex). Then run aidlc doctor; for a copy install, verify bun is on PATH
Subagent timed out Run /aidlc to retry or run the stage inline
Workflow stuck or misbehaving, need help Run /aidlc --doctor --export and share the produced .tar.gz (redacted; no work product)
A Bolt attempt was set aside Ask the assistant to invoke the saved abort result's restore_operation with its exact argv; hints are display-only. Evidence-only attempts have no saved files to restore. See getting the files back

Native Install Channel

Symptom or error Resolution
Checksum mismatch for <asset>. or <asset>: checksum mismatch Stop. Do not reuse the downloaded directory. Download the complete release asset set and checksums.txt again from the same release.
command not found: aidlc after install.sh Add the installer-reported bin directory to PATH (normally export PATH="$HOME/.local/bin:$PATH"), open a new shell, and run aidlc doctor.
aidlc is not recognized after install.ps1 The default install registers User PATH for the account that ran PowerShell. A terminal app or IDE that was already open during the install (Kiro, VS Code, Cursor) keeps the PATH it started with: quit it fully and reopen it. A new tab or Reload Window inside it is not enough. With -NoModifyPath, use the printed direct command (normally & "$env:LOCALAPPDATA\aidlc\bin\aidlc.cmd" config) or rerun the installer without that switch to register PATH.
aidlc works in PowerShell or CMD but not in Git Bash (or another MSYS shell) Those shells resolve a command with Unix execvp rules and ignore PATHEXT, so a bare aidlc never finds aidlc.cmd. The installer writes an extensionless aidlc launcher beside aidlc.cmd in the bin directory (normally %LOCALAPPDATA%\aidlc\bin) precisely so the bare name resolves in these shells; if it is missing, rerun the installer or aidlc use <version> (from PowerShell or CMD, where aidlc already resolves) to rewrite it. One known cause of a hook that /hooks lists as registered yet never fires on Windows is this: the hook shell cannot resolve aidlc. aidlc doctor shows it as a failed Windows launcher (Git Bash) row that names the step to take. If a file named aidlc that AI-DLC did not write (for example an earlier hand-made forwarder) is already in that bin directory, the installer, aidlc update and aidlc use ask once at a terminal whether to replace it, and keep your file as aidlc.bak-<time> beside it. --yes (-Yes for the installer) answers yes. Without a terminal or --yes, they leave the file as it is and say to move it aside. A directory named aidlc there is never replaced: remove or rename it, then rerun the installer or aidlc use <version>.
This PowerShell window is running as administrator For the safest install, answer N, open PowerShell normally (not "Run as administrator"), and run the installer again. To continue as administrator anyway, answer y, or pass -Yes to the installer. aidlc uninstall asks nothing: it prints the same warning and goes ahead, so for the safest uninstall run it from a normal PowerShell window. AI-DLC is per-user and does not need admin rights. The built-in Administrator on Windows Server and other sessions without UAC elevation see no warning.
Windows install reports a PATH conflict The files are installed, but persistent PATH selects another command. Use the printed full command path for config, or resolve the reported conflict. JSON reports status: "warning" and data.ready: false even though the exit code is 0.
Windows install reports that it could not configure PATH The files are installed; the PATH step failed with exit code 1. Follow the printed recovery instruction, or rerun with -NoModifyPath and use the direct command. JSON reports data.installed: true and data.ready: false.
User PATH entry remains after Windows uninstall Uninstall removes only an entry owned through windows-path.json. A pre-existing entry or an install without that ownership record leaves User PATH unchanged. See Uninstall.
Files remain after uninstall Uninstall deletes individually verified files and removes directories only when empty. Unlisted or changed files are preserved and reported, including files without an ownership inventory in older installs. Review the reported paths; --purge does not delete unrelated content.
--offline requires --from <release-directory> Offline mode never falls back to a network release. Transfer the complete release asset set, then pass its directory with --from / -From; the installer verifies it.
aidlc.cmd exits 4 or the Windows active pointer is invalid The launcher prints one aidlc: line naming the file it could not use (the active version marker, the active command target, or the active executable) followed by Rerun the AI-DLC installer (install.ps1) to repair the aidlc command. After aidlc update from an earlier release, that release's launcher, which exits 4 without printing anything, stays until the next aidlc command other than aidlc doctor or aidlc uninstall replaces it; that one command still runs through the old launcher, which splits a value with spaces into separate words. While it is there, aidlc doctor shows a Windows launcher row; when AI-DLC cannot replace it (for example because aidlc.cmd or aidlc-shim.ps1 was changed after install), the row says why and names the step that fixes it. If the old launcher exits 4 before any command starts, rerun the installer. Do not edit %LOCALAPPDATA%\aidlc\active-executable. Rerun the same verified installer or use aidlc use <version> from a working retained executable. A line that says PowerShell runs the launcher in ConstrainedLanguage mode means an application control policy (AppLocker or WDAC) blocks it: ask your administrator to allow aidlc-shim.ps1, or run %LOCALAPPDATA%\aidlc\versions\<version>\aidlc.exe directly.
aidlc-shim.ps1 cannot be loaded or is not digitally signed A Group Policy execution policy overrides the -ExecutionPolicy Bypass that aidlc.cmd passes, so PowerShell refuses the launcher before it runs. Run Get-ExecutionPolicy -List: a MachinePolicy or UserPolicy row other than Undefined is the cause. Ask your administrator to allow the script, or run %LOCALAPPDATA%\aidlc\versions\<version>\aidlc.exe directly.
pending Windows uninstall or a Windows uninstall recovery failure Close active AI-DLC commands and run aidlc doctor. A pending cleanup resumes on the next command. If doctor reports a failed cleanup, resolve the reason it shows and run aidlc uninstall again by the full path doctor prints (normally & "$env:LOCALAPPDATA\aidlc\bin\aidlc.cmd" uninstall, since the PATH entry may already be gone; add --purge if the original used it): a cleanup that failed before removing files is planned again from disk, and one that had begun resumes. If that command no longer runs, run the installer again; it retries the pending cleanup first, so you may need to run it twice. Older or altered journals without a bound file plan are refused; keep the temp journal, cleanup script, machine fence, and remaining files for inspection.
a Windows uninstall cleanup is still running A cleanup worker was launched in the last few minutes. Wait for it to finish, then rerun the command.
Alpine reports missing libstdc++.so.6 or libgcc_s.so.1 Install the same runtime dependencies required by Bun's and Node.js's musl builds with apk add libgcc libstdc++, then rerun the installer or command. Fully static Bun musl compile targets are not available today; the installer reports this remediation but does not install packages.
Providers shows [needs] with no recorded answers although the harness already has its own model access On Kiro CLI and Kiro IDE the row reads [ok] and aidlc config providers asks nothing, because model access comes with Kiro. On GitHub Copilot and Cursor the row reads [ok] with no answer, because the session brings model access; run aidlc config providers only to use your own Amazon Bedrock access (on Cursor, only the IDE takes Bedrock keys; its CLI always uses Cursor's backend). On every other harness the row is genuine: answer amazon-bedrock, or choose keep current (--provider current) to preserve and record the provider already configured for the harness. --provider other --acknowledge records a different provider you configured yourself.
Models shows [needs] with no recorded policy With no policy, most agents inherit your session's model and effort, so a session at high effort runs them at high effort. Record a preset to set agent efforts (aidlc config models --preset balanced --project --yes), or leave it to keep inheriting. On Kiro CLI a preset sets one effort for the whole interactive session: aidlc config models chooses the session model and saves it with that effort in your personal Kiro settings, and /model and /effort change them inside Kiro (see Session model and effort). On GitHub Copilot, Cursor, and Kiro IDE the row reads [ok] and names the host instead, because a preset changes nothing there: choose the model and effort in the host (on Kiro, aidlc config models --agent sets one agent's own model and effort). See Choosing a Model and Effort.
workspace shell ready fails in aidlc doctor and rerunning aidlc config does not fix it The interactive rerun uses the existing projection and never rebuilds a missing aidlc/spaces/default/memory/; while the shell is incomplete it reports a Workspace row and offers no sections to fix. Run the command that row names. On a native install that is aidlc config --harness <name>, which refreshes from the installed runtime and recreates the workspace shell. A Bun-invoking projection, copied from the runtime/<name>/ root of aidlc-copy-runtime-X.Y.Z.tar.gz or from a checkout's dist/<name>/ tree, has no installed runtime to refresh from, so its command also carries --download, which fetches and verifies aidlc-copy-runtime-<version>.tar.gz for the project's release. It never uses the native aidlc-runtime-X.Y.Z.tar.gz or dist-release/ bytes, which would swap the project's hooks to the native command.
aidlc config says it needs a release: this project is pinned to <version>, needs the <version> release files, is missing aidlc/spaces/default/memory/, or no longer has the MCP server list The project needs files for a release this machine does not have: a teammate's newer pin, a harness you are adding, or files it lost. Run the fix: line: it is your command with --download, which fetches exactly that release, verifies its checksum and (when gh is installed) its release attestation, and finishes the command. Natively that installs and registers the pinned release, as aidlc config --pin does; on a copied project it downloads aidlc-copy-runtime-<version>.tar.gz. At a terminal config asks instead. A pinned release already installed is used without asking. Without network access, follow the offline: line: fetch the named file elsewhere and pass it with --from, or natively aidlc config --pin <version> --offline --from <release directory>. --release-base-url and --ca-bundle choose a mirror. A failed checksum or attestation stops with nothing changed.
aidlc doctor asks for Bun on a project you did not install through the copy channel Copy-channel projections run hooks through Bun; native installs run them through the aidlc command. The remediation names which channel the project is on. To stop needing Bun, reinstall through the native release installer and rerun aidlc config --harness <name>.
Harness trees on different releases in aidlc doctor The project's harness trees were installed from different releases, so a workflow can behave differently in each tool. Run the commands the row names. A pinned project's trees are brought to the pin. Natively that is aidlc config --harness <name> for each tree not on the engine's release (or the pin). On a pinned copied project it is bun <harness-dir>/tools/aidlc.ts config --harness <name> --download; without a pin it is bun <harness-dir>/tools/aidlc.ts config --harness <name> --from <file> with the newest tree's aidlc-copy-runtime-<version>.tar.gz, after one --download refresh for a tree no config run has recorded. Open work carries on through the refresh, so there is no need to wait for it to finish.
config plan changed after approval Rerun aidlc config --dry-run --json, review data.actions, and apply the new data.planToken with exactly the same source and behavior options.
locally modified or managed block was locally modified from aidlc config Run aidlc config --dry-run --json and review data.actions. Use --force only to replace baseline-owned framework bytes or managed blocks; it never authorizes unrelated root content. .claude/settings.json is merged by entry, so it does not need --force: a refresh puts back AI-DLC's hooks and command allow entries and keeps your hooks, deny rules, custom statusline, environment, and other settings, with a note saying what it put back. Retired shipped allow entries are not removed automatically. .codex/config.toml is merged by entry the same way: a refresh changes only AI-DLC's own keys, keeps your keys, tables and comments as they are, and keeps a value you changed in one of AI-DLC's keys, with a note when the release ships a different one.
AI-DLC files: N changed in this project in aidlc doctor Those AI-DLC files were edited in this project, so aidlc config keeps them and stops before it refreshes anything. To keep your version, move the named files somewhere else, then run aidlc config; to take the shipped versions over them, run aidlc config --force. A file whose only difference is its line endings (a Windows checkout turns LF into CRLF) is never counted.
cannot coexist in one project The second harness shares an engine directory (opencode / copilot use .aidlc) or an exclusive managed block (Copilot's AGENTS.md). Choose distinct engine directories and avoid exclusive blocks. kiro and kiro-ide also share .kiro, but aidlc config --harness kiro-ide (or --harness kiro) switches an installed one to the other in place; see More than one harness in a project. The neutral AGENTS.md block is shared across Kiro CLI, Kiro IDE, Codex, Cursor, and OpenCode; .gitignore combines shipped entries.
cannot switch .kiro from <row> to <row>: installed <row> has no ownership baseline, has an ownership baseline recorded before it listed only shipped files, or has an unusable ownership baseline Nothing usable records which .kiro/ files the installed row owns, so the switch would leave its files behind; it changes nothing. Follow the printed steps: move a damaged .kiro/tools/data/aidlc-manifest.json aside (the step names its full path), run the printed config --harness <installed row>, then run the switch again.
switching .kiro to kiro-ide lets Kiro run hook files AI-DLC does not own Kiro runs every .kiro/hooks/*.json file on its v3 engine and in Kiro IDE. Review the named files, then answer the prompt in a terminal, or run the printed --dry-run and apply the switch with the --plan-token it prints. config plan changed after approval or hook files AI-DLC does not own changed after this switch was planned means the set changed after review; review it again.
cannot switch .kiro to kiro-ide: .kiro/hooks is a link or a file, not a directory, or Kiro would run hooks through entries that are not regular files in .kiro/hooks Make .kiro/hooks a real directory holding its files; or replace each listed hook entry (a link, a directory, or another non-file) with a regular file or move it out of .kiro/hooks. Then run the switch again.
predates shared onboarding The named installed harness is older than the selected release (or has no valid recorded version) and its block is not shared. A preview sorts before the stable release with the same base version. Try refreshing it with aidlc config --harness <name> before adding another harness that shares the neutral AGENTS.md block. This is a hint for an older sibling: if it still refuses afterwards, its block is exclusive and they cannot coexist in one project. Copilot's block stays exclusive after refresh. Current exclusive blocks instead report cannot coexist in one project. --force does not bypass this compatibility check.
refusing to refresh <harness> from a release whose AGENTS.md is not shared Another installed harness shares the neutral root block, but the selected refresh source does not declare it shared. Use a release that declares AGENTS.md shared; --force does not bypass this guard, and no project files are changed.
shared block is owned by <harness> from a different release The shared AGENTS.md block matches the named sibling's baseline, not the selected release. Follow the refresh order in the error: refresh the selected harness from the same release as its sibling, or refresh the sibling from the selected release first. No project files are changed by the refused refresh.
multiple project harnesses are present; pass one --harness <name> Every aidlc config on a multi-harness project must name the target with --harness <name>, except recording or clearing a bypass (aidlc config flags --bypass <NAME> or --clear-bypass <NAME> with nothing else to change), which belongs to the project and needs no harness.
.gitignore shows preserve (owned by <harness>) (action: "preserve", detail: "owned by <harness>" in aidlc config --dry-run --json) This fallback appears when the owning harness was installed by a release without tools/data/root-blocks/. Run aidlc config --harness <owner> to refresh it, after which both harnesses converge on one combined block.
managed block has no ownership baseline The block was written by an install that no longer exists or has no baseline, for example a removed harness tree. Review aidlc config --dry-run --json, then use --force to replace it with the current shipped block (the combined entries for a shared .gitignore).
has no readable projection descriptor or has lost its projection descriptor and ownership baseline Repair the named installed harness with aidlc config --harness <name> before adding another harness. For co-owned blocks, a same-release refresh is allowed when the source declares the block shared and leaves the current block unchanged, matching the sibling's baseline, even when that sibling's descriptor is missing; this allows both missing descriptors to be repaired one harness at a time. Otherwise, a co-owns AGENTS.md refusal requires restoring the named sibling's descriptor first; --force cannot bypass this guard. A stamped sibling (aidlc-stamp.json present) that has lost both its descriptor and its baseline blocks a refresh that would change a non-union managed block with has lost its projection descriptor and ownership baseline; restore that sibling first. A same-release refresh that leaves the current block unchanged is still allowed, but --force cannot permit a block-changing refresh. Legacy trees without a stamp and without baseline evidence of co-ownership can still be adopted one harness at a time.
is missing its shipped block copy The named harness's install lost tools/data/root-blocks/<marker>. Run aidlc config --harness <name> to restore it, then rerun the refresh. --force writes the block without that harness's entries.
unowned whole file from an ordinary aidlc config release refresh Move or merge the existing file manually before refresh. OpenCode's opencode.json no longer stops here: config adds AI-DLC's entries to your file and keeps everything else in it.
opencode.json stops config with <key> must be a JSON object or must be a JSON array AI-DLC adds its entries to skills.paths, instructions, and permission; when one of those has another shape (for example "permission": "ask"), config changes nothing. Write it as a map or a list ("permission": { "bash": "ask" }), then rerun config.
<file> is not valid UTF-8; convert its encoding before config Back up the named root file (such as .gitignore or AGENTS.md) and convert it from its current encoding to UTF-8, keeping its content, then rerun config. AI-DLC leaves the original bytes untouched when decoding would lose information.
managed markers are missing, duplicated, or malformed Repair the named root file so it has exactly one matching BEGIN AI-DLC / END AI-DLC pair, or remove the broken AI-DLC block and rerun aidlc config.
project runtime <version> is incompatible with selected engine <version> Run aidlc use <version> to install and select the compatible version, or refresh the project intentionally with aidlc config.
this project requires <version>, which is not installed completely Install or reinstall the exact strict-semver pin with aidlc config --pin <version>. The dispatcher fails closed instead of falling back to the active machine version; use aidlc config --unpin only when the team intends to stop pinning the project.
.aidlc-version must contain one release version id The committed pin file holds something other than one release id, such as extra text or a stray command. aidlc config and the dispatcher refuse it without printing its contents. Fix the file to the intended release id (for example 2.10.0), or run aidlc config --unpin to stop pinning the project.
AI-DLC can't run in <folder>. Start the session from your project's folder. when you ask for AI-DLC The session started in a folder that holds AI-DLC's machine install or command directory, such as your home folder, or in a folder inside one. AI-DLC does not run there, so its hooks stand aside and your other work in that folder goes on as usual. Start the session from your project's folder to use AI-DLC.
An update was interrupted and aidlc version still shows the prior release This is the safe restored state: the old command remains active. Run aidlc doctor, then rerun the same aidlc update --version <version> command.
another AI-DLC mutation holds .../.aidlc-transaction.lock, cannot verify a lock, or belongs to another host or boot Let an active owner finish; otherwise follow Transaction lock ownership.
an earlier AI-DLC command stopped before it finished, so its lock was cleared Nothing to do for the command you ran. The earlier command did not finish: rerun it if you still need it.
another AI-DLC command is still changing this machine's install, so this ran on aidlc <version> without waiting for it to finish Nothing to do: a command or hook in a pinned project waited up to 30 seconds for an update, uninstall, or other machine change, then ran on its pinned release anyway. If it repeats while no other aidlc command is running, follow Transaction lock ownership.
EMLINK (too many links), Cannot create an AI-DLC transaction lock, or Cannot use the filesystem at ... during config Hard links have an automatic fallback; other filesystem requirements still apply. See Config fails with a hard-link error.
existing aidlc is managed by Homebrew / Nix, or the destination command is not owned by the AI-DLC installer Upgrade through the reported owner. To keep a separate native install, set AIDLC_BIN_DIR explicitly to an empty user-owned directory. This release does not itself ship Homebrew or Nix packaging and never replaces a mixed-ownership command.
update cache is invalid or machine settings are rejected Run aidlc system config global list. Repair or remove only the named %LOCALAPPDATA%\aidlc\aidlc.settings.json (Windows) or ${XDG_DATA_HOME:-$HOME/.local/share}/aidlc/aidlc.settings.json (macOS/Linux); unknown keys and stored credentials are rejected.
HTTPS_PROXY must use HTTP or HTTPS or a release URL is rejected Use an HTTP(S) proxy URL and an HTTPS release mirror without credentials, query, or fragment. The native client reads HTTPS_PROXY and NO_PROXY, not HTTP_PROXY, and redacts secret-like URL parts in errors.
Download fails behind a corporate CA Pass --ca-bundle <absolute-path> or set AIDLC_CA_BUNDLE. The Windows bootstrap requires curl.exe when a custom CA is supplied.
host inventory unavailable from a plugin command Run sync from a host session that injects the current plugin root, or restore the Claude/Codex host registry. Missing or malformed inventory is never treated as proof that content is safe to prune.
Nothing synced: this tool keeps no list of your plugins Kiro CLI, Kiro IDE, Cursor, Copilot and opencode have no plugin list: run the command the line names with each plugin's folder after --plugin-root.
cannot sync <plugin> or cannot prune <plugin>: owned path changed since composition You edited a file the plugin added. To keep the edit, move that file somewhere else, then run the command the line names (the same aidlc engine plugin sync, with the plugin's folder on a host with no plugin list, or sync --prune-missing) again; sync puts the plugin's own version back. --yes does not override ownership hashes.
aidlc system versions prune, uninstall, or plugin prune requires --yes The command is running without an interactive stdin. Review the listed removals, then rerun with --yes; integrity refusals cannot be bypassed. At a terminal these commands ask nothing: they print what they remove, then do it.
aidlc setup is unknown, or an npm install is unavailable Those channels are planned but not shipped. Use the release installer plus aidlc config; do not treat proposal transcripts as available commands.

Native aidlc doctor also checks the active command pointer, rollback eligibility, retained pin completeness, stale pin registrations, abandoned transaction staging, project version skew, and whether binary-channel host hooks and permission/trust entries consistently select the native command.

Config warns about an ignore rule hiding committed records

In a Git repository, config checks whether one of your own ignore rules hides records meant to be committed and shared. A rule such as aidlc/ does, so config still finishes but ends with a note naming <file>:<line> and the hidden record paths (memory/**, codekb/**, intents.json, aidlc-state.md, and audit/*.md): new ones will not reach teammates, though files git already tracks keep being committed. The first-run setup and --quiet show it too. If that is not what you intended, narrow the named rule, preserving unrelated ignores. A deliberate rule, such as one keeping a personal scratch space out of Git, can stay. Outside Git, or without the Git executable, there is no check.

aidlc config first attempts a hard-link transaction lock. If the mount rejects it with EMLINK, ENOTSUP, EOPNOTSUPP, ENOSYS, or EPERM, config automatically tries a directory lock at the same .aidlc-transaction.lock path. No flag is needed, and config never proceeds with unlocked writes.

The first-run wizard probes the required filesystem operations before offering setup choices, then removes its temporary probe files. A failed probe stops setup with nothing written; if a probe itself cannot be removed, setup names it and says nothing else was written. Human output names the failure and the fix; --quiet prints the fix, and --json returns a structured failure. Passing probes cannot certify atomicity or crash durability. See the capabilities and support matrix in Transactions and Recovery. An S3 mount name or hard-link error alone does not identify its driver, version, or options.

For an incompatible mount, move or clone the project onto compatible local storage, such as ext4 or XFS on an EC2 EBS volume, and rerun aidlc config there. Keep the working project outside the S3 mount; any later upload is a separate publication, without an atomic multi-file guarantee. An alias or symlink to the same mount does not change its capabilities. Neither --force, --from, nor deleting locks repairs missing filesystem semantics.

Transaction lock ownership

Let a live init/lifecycle owner finish before retrying. The next AI-DLC command clears a lock whose owner has stopped and says so in one line. An owner has stopped when its PID is dead, or when the system has since given that PID to a later process (Windows reuses PIDs quickly): one whose start record differs from the one the lock recorded, or, for a lock from a release that recorded none, one that started after the lock was written. A directory lock also needs its recorded host/boot identity to match. Foreign, incomplete, or unverifiable directory owners are retained; a PID absent on this host is not proof that a foreign owner has stopped.

For manual diagnosis, preserve the error, lock, and named staging/recovery paths. Inspect .aidlc-transaction.lock/owner.json (the lock file itself for a legacy file lock), and establish the owner process, host/boot, and mount history with the operator. All participants must share the same local temporary directory (TMPDIR on Unix) and PID namespace. Stop writers before corrective work and retain the evidence while ownership is uncertain. Do not blindly delete the project lock or its local coordination gate to make a retry proceed.


Hooks Not Firing

Symptom: No entries appearing in the intent's audit/ shards after file writes, or no subagent completion logs.

Native runtime versus source-generated Bun projection

The source/development dist/ projection runs its 17 TypeScript hooks through bun. Native installs and versioned release runtimes route those same hooks through aidlc. If a source-generated install cannot find Bun on the non-interactive PATH, its hooks will not fire.

# macOS / Linux
curl -fsSL https://bun.sh/install | bash

# Windows
npm install -g bun
# or: powershell -c "irm bun.sh/install.ps1 | iex"

# Verify
bun --version

For a source-generated dist/ install, bun must be on the PATH the harness hands its hooks. A harness started from a terminal hands them that terminal's PATH, so bun --version working there is enough. A harness started from the dock, a desktop icon, or a service does not get that PATH. If its hooks do not run, open a terminal where bun --version works and run bun <harness-dir>/tools/aidlc.ts doctor there (for example bun .kiro/tools/aidlc.ts doctor): its Runtime hook PATH row names the directory to add and where. Restart the harness afterwards. Until then, start it from that terminal. On native Windows PowerShell, the system PATH entry set by npm install -g bun is sufficient.

Kiro IDE hooks not running

Kiro IDE runs a folder's hooks only after you allow it to run commands in that folder and then reload the window. Until you allow it, every command the agent runs comes back with no output and exit code -1, so no AI-DLC message can show; the agent gives you the step itself. If you trusted the folder after Kiro opened it, commands run but the hooks still do not until the reload: AI-DLC then stops before any work and the agent shows you the same step. Before your first chat message in the project, doctor warns "AIDLC hooks have not run in this project yet"; that is expected.

Trust only a folder whose contents you know (your own project, or one you have checked), because trusting lets the folder's .kiro hooks run commands on your machine (see First run).

  1. Choose Trust Folder & Continue when Kiro asks whether you trust this folder. If the Restricted Mode banner shows at the top of the window instead, select Manage on it, then Trust.
  2. Open the Command Palette (Ctrl+Shift+P, or Cmd+Shift+P on macOS) and run Developer: Reload Window. Trust takes effect after the reload.
  3. Say carry on in the chat. If your next message is still not recorded, /aidlc --doctor shows why.

Kiro CLI hooks not running

Kiro CLI's v2 and v3 engines read different hook registrations. If the engine does not match the AI-DLC distribution you installed, no hook runs. Every approval and confirmation then says no human reply has arrived, reviews say the output has no recorded write, and, after the first workflow stage, doctor reports "Hooks have never executed". Restarting on the same engine changes nothing.

  • kiro distribution (.kiro/agents/aidlc.json): hooks run on Kiro CLI's v2 engine, with the aidlc agent active; v3 does not run the file as AI-DLC ships it. With another agent picked, type /agent and pick aidlc, then carry on in the same chat. If Kiro prints agent "aidlc" needs upgrading for this agent engine under its replies, the session is on the 3.0 engine: quit Kiro and start it again in this folder with kiro-cli chat --agent-engine v2 --agent aidlc. From an ACP client, start kiro-cli acp --agent-engine v2.
  • kiro-ide distribution (.kiro/hooks/aidlc-*.json): hooks run only on Kiro CLI's v3 engine. kiro-cli chat reads the v3 pin in .kiro/settings/cli.json; kiro-cli acp does not, so an ACP client must start kiro-cli acp --agent-engine v3. It must also declare clientCapabilities._meta.kiro.hooks as { enabled: true, v2: true } in its initialize request. Without both values, v3 runs no hooks.

These behaviours were measured on Kiro CLI 2.21.1, and a later Kiro CLI may change them. After you switch, send a message and run /aidlc --doctor. On the kiro distribution, your message leaves the first heartbeat, so doctor confirms the hooks from then on; until then it warns that they have not run in this project yet.

GitHub Copilot hooks not running

VS Code runs a project's hooks only in a trusted workspace with the Chat: Use Hooks setting (chat.useHooks) on, and your organization can switch that setting off. aidlc config turns it on in the folder's .vscode/settings.json when the project does not set it, and a folder's value beats a user setting that is off. The Copilot CLI runs hooks only in a folder it trusts. Neither says anything in the chat when it skips them, so AI-DLC does: when no hook has run for your message, the agent turns the folder setting on itself and shows one line. Send your next message in the same chat; no new chat or reload is needed. Before your first Copilot chat in the folder, doctor warns "AIDLC hooks have not run in this project yet"; that is expected until a chat has started.

  1. In VS Code, VS Code asks the first time whether you trust the folder's authors; trust it. If your organization has switched Chat: Use Hooks off, only your administrator can turn it back on.
  2. In the Copilot CLI, trust the folder when it asks. A headless copilot -p run never asks: start copilot in the folder once and choose "Yes, and remember this folder for future sessions".

See GitHub Copilot for the folder trust details.

Codex CLI hooks not trusted

Codex runs a project's hooks only once you trust them in its /hooks screen, and it asks again when the hooks change. In Codex, type /hooks, press t to trust all, then press Esc, and carry on in the same chat. Nothing outside Codex can do this for you.

opencode plugin not loaded

opencode loads AI-DLC's plugin only when it starts plainly in the project folder: not under --pure, and not from a subfolder. Quit opencode and start it again with just opencode in the project folder, then type /aidlc to carry on. When the agent stopped a request of yours with this step, type the /aidlc --request <id> line it showed you instead: that request carries on, once.

Claude managed policy blocks project hooks

If /hooks reports that hooks are restricted by policy and shows zero configured hooks, run /aidlc --doctor. On Claude Code, doctor reads /Library/Application Support/ClaudeCode/managed-settings.json on macOS, /etc/claude-code/managed-settings.json on Linux/WSL, or %ProgramFiles%\ClaudeCode\managed-settings.json followed by the legacy %PROGRAMDATA%\ClaudeCode\ location on Windows. Each candidate also includes alphabetical JSON fragments under its sibling managed-settings.d/ directory. An effective top-level allowManagedHooksOnly: true blocks every project hook declared in .claude/settings.json. Set AIDLC_MANAGED_SETTINGS_PATH when the managed file lives elsewhere; its sibling fragment directory is included automatically.

Only your Claude Code administrator can lift this managed setting: ask them to allow project hooks.

Cursor project outside a git repository

If Cursor keeps asking you to approve the same plan, or says your choice did not get recorded, run /aidlc --doctor. Cursor may skip project hooks in a folder that is not in a git repository, and without the hooks your approvals are never recorded. When doctor fails "project is in a git repository", run git init in the project, then fully restart Cursor and trust the folder when asked. aidlc config --harness cursor and the copy installer print the same advice when they set up a project outside a git repository.

Reviewer tool calls refused ("This review cannot open ...")

During a per-unit Construction review, the reviewer-scope hook refuses the dispatched reviewer's tool calls that reach into sibling units' construction/ paths (the read-scope bound in stage-protocol-reviewer-unit.md); the refusal names the current unit and directs the reviewer to the supplied files and that unit's own path, and each refusal records a REVIEWER_SCOPE_BLOCKED audit row. If your own source tree contains a construction/ directory unrelated to AI-DLC units (so legitimate reviewer reads are being refused), /aidlc config set guard.reviewer-scope off lowers just the reviewer read-scope check for the piece of work you are on (recorded as a GUARD_DISABLED audit row, back on for the next one), and AIDLC_DISABLE_REVIEWER_SCOPE_HOOK=1 disables that read-scope enforcement machine-wide; the prose bound still governs under either. Neither setting permits a claimed team checkout to write another Unit's construction/ subtree. A general request in chat does not lower the read-scope check: type the switch above and the agent runs the setter for it. Changing scope alone never lowers the running policy. A reviewer being refused with NO review in flight means a stale dispatch record - check /aidlc --doctor's hook-drop counters (reviewer-scope.drops) and delete <record>/.aidlc-engine/reviewer-dispatch.json if present (records older than 6 hours are ignored and cleaned automatically).

Ordinary filters such as grep latency construction/U03-scoring/nfr.md | grep endpoint are allowed because the second grep searches the piped text. A pipe does not exempt commands that still traverse files: recursive grep, rg --files, and rg -f - still need an in-scope search root or, for rg, a glob constrained to the current unit. Pattern files supplied with -f must also be in scope. When a pathless command falls back to . and is refused, the message identifies that root as implicit.

Sensors are not firing

Check the Sensors row in /aidlc --status. The classic scope defaults to Sensors on. If an intent override or kill switch turns Sensors off, automatic write-time checks, gate-start checks, revision checks, and approve-time revision-backstop checks do not run. /aidlc --sensors on opts the active intent back in. AIDLC_DISABLE_SENSORS=1 takes precedence over that intent setting; unset it (and any recorded project bypass) to allow automatic checks again. All hooks stay installed, and explicit aidlc engine sensor fire remains available for diagnostics even when automatic sensors are off.

Statusline shows a cost segment you don't want (or usage tracking concerns)

On Claude Code, per-stage token usage and cost tracking is on by default: the fold-usage hook records transcript usage into a gitignored local ledger (aidlc/.aidlc-sessions/usage-ledger.json), the statusline appends ↑<in> ↓<out> $<usd>, and completion audit events carry cost rollups. Nothing is transmitted anywhere (metrics emission is separately opt-in via AIDLC_METRICS_ENDPOINT). To turn all local tracking off, set AIDLC_DISABLE_USAGE_TRACKING=1: the ledger stops updating, the statusline segment disappears, and completion events add no rollup fields. An existing ledger is left on disk; delete it manually if you also want the history gone. Unsetting the flag resumes tracking.

The $<usd> figure is a local estimate, not a bill. It is priced from public list prices in the shipped rate table (see Rate table and overrides). When Amazon Bedrock is the recorded provider (CLAUDE_CODE_USE_BEDROCK=1), what Bedrock actually charges depends on your inference profile, region, service tier, and any negotiated or subscription pricing, so the estimate may not match your invoice. Most of the token volume in a long workflow is cache reads — billed, at the reduced cache-read rate — so the counts and the estimate grow steadily; that is real usage, not inflation. Treat the number as a personal awareness signal.

To price the estimate at your own rates, set AIDLC_MODEL_RATES to a rates file with the same shape as the shipped .claude/tools/data/model-rates.json (USD per million tokens, one key per model version, so opus-5-5 and opus-5 are separate rows). A partial file only changes the models it names; everything else keeps the shipped defaults. Rates are applied as usage is recorded, so a change prices turns from that point on; totals already in the ledger keep the rates they were recorded at.

If you'd rather not show the estimate — while presenting, screen-sharing, or recording — turn the cost segment off. Add the kill switch to the gitignored .claude/settings.local.json (it only removes the token/cost segment — the workflow is unaffected):

{
  "env": {
    "AIDLC_DISABLE_USAGE_TRACKING": "1"
  }
}

Hook not configured

Hooks are registered project-wide in the harness's native configuration. On Claude, verify that .claude/settings.json contains the expected hooks events. For a native project, complete active workflows, then run aidlc config --harness claude to restore the shipped registrations; your own hook entries are kept. A copy-channel project instead uses bun .claude/tools/aidlc.ts config --harness claude --from <the runtime/claude root you copied from>. No --force is needed. Notes tell you when registrations were restored. Doctor fails when a flow-altering registration changes its event, matcher, or command, or when a shipped hook is no longer wired. Drift in other AI-DLC registrations produces a warning. Your own additional hooks do not trigger drift warnings. A status line your team set in that file is kept. AI-DLC's own status line is not shipped there: each person turns it on for themselves with /aidlc --statusline on. For a manual copy, replace the complete harness root from the same versioned runtime/<harness>/ archive (a copy never replaces your .gitignore or AGENTS.md); do not patch one hook command in isolation. The manual archive is Bun-shaped and does not require the native aidlc executable.

Hooks disabled globally (disableAllHooks)

Claude Code honours "disableAllHooks": true in any settings layer: enterprise managed settings, .claude/settings.local.json, .claude/settings.json, or ~/.claude/settings.json (or settings.json under CLAUDE_CONFIG_DIR when that is set). When set, every hook is silently skipped even though the files are present and correctly wired, so the workflow cannot record your replies. /aidlc --doctor detects this and fails a Hooks enabled row naming the offending layer, following Claude Code's layer precedence so a higher-precedence false suppresses a lower true. When no hook has run for your message, the agent makes the change below itself before any work, and Claude Code asks you first.

  • If the offending layer is a project or user file, set "disableAllHooks": false in this project's .claude/settings.local.json. That file outranks the project and user files, so it covers a switch-off in any of them without changing your user settings, and it works in the same chat: no restart and no /hooks.
  • If it is enterprise managed settings, the highest-precedence layer, a project or user file cannot override it: ask your Claude Code administrator to allow project hooks.
  • If you started Claude Code with a setting that turns hooks off (for example --settings '{"disableAllHooks": true}'), a project file cannot override it either, and doctor cannot see it: start Claude Code again without that setting.
  • If AI-DLC was set up while Claude Code was already open in this folder, that session never loaded its hooks (on a native install they call aidlc, which the open session cannot find yet): exit Claude Code and start it again in this folder, then type the line the agent showed you: /aidlc --request <id> carries on with the request it stopped, once, and /aidlc alone carries on where the work stands.

The check reads the on-disk managed-settings file (/etc/claude-code/managed-settings.json on Linux, /Library/Application Support/ClaudeCode/managed-settings.json on macOS, %ProgramFiles%\ClaudeCode\managed-settings.json on current Windows — %PROGRAMDATA%\ClaudeCode\ is a legacy secondary) plus alphabetical JSON files in the sibling managed-settings.d/ directory. It does not inspect other managed channels Claude Code supports (MDM, Windows registry, or a remote/server-managed source), so a passing row means the resolved value is not true in any settings file the check could read, not a guarantee those channels are clean. If your managed file lives at a non-standard path, point the check at it with AIDLC_MANAGED_SETTINGS_PATH=/path/to/managed-settings.json; fragments beside that file are included.

A Kiro hook switched off under Agent Hooks

Kiro lets you switch any project hook off in its Agent Hooks panel, and then writes "enabled": false into that hook's file in .kiro/hooks/. The hook stops running with no other sign. /aidlc --doctor reads that flag on every AI-DLC hook file. When aidlc-guard-tool-call is off, the approved plan, reviewed work and AI-DLC's records are not protected; when aidlc-record-human-turn is off, your replies are not recorded, so an approval waits for an answer it cannot see, and /aidlc commands typed in chat are not run directly. Either one fails a row naming the hook, and so does aidlc-continue-workflow, which keeps a workflow moving where Kiro lets a Stop hook block (Kiro CLI v3; Kiro IDE only records it). Any other AI-DLC hook switched off is a warning that says what is lost. Turn the hook back on under Kiro's Agent Hooks, or set "enabled": true in the file doctor names. The next AI-DLC step says the same once per change, as one line before its work, and while aidlc-record-human-turn is off an approval tells you to turn it back on under Agent Hooks rather than to trust the folder; nothing turns a hook back on for you.


Kiro IDE Read Denials

Kiro IDE denies every read under .kiro/ ("Rule: deny fs_read matching")

Symptom: Every stage, agent, and protocol read is denied, blocking the workflow:

Tool call denied by user's permissions. Rule: deny fs_read matching ".kiro/" Source: ~/.config/git/ignore

Kiro IDE honours git's global excludes file (in git repositories) and ~/.kiro/settings/kiroignore automatically. Workspace ignore files apply only when the IDE's kiroAgent.agentIgnoreFiles setting names them (the default includes .gitignore; [] disables workspace sources). It evaluates each ignore file on its own: a project !.kiro/ negation does not undo a global .kiro/ rule, even when git check-ignore reports the path as not ignored. A permissions.yaml fs_read allow does not clear the denial: Kiro applies deny-overrides across scopes.

Run /aidlc --doctor. For an IDE install (.kiro/agents/aidlc-aidlc.md present), it reports the offending source as:

Kiro IDE ignore sources: <source>:<line> hides .kiro/

Doctor tests the reads the engine sends the agent to make through fs_read, from the engine's own roster: for every stage that harness.json selects in the compiled stage graph, the stage file and the persona and knowledge the conductor holds inline (at Standard and Minimal depth, within the directive's 8 KiB inline_context_paths cap), plus stage-protocol.md and its stage-protocol-<name>.md modules and the files beside each skill's SKILL.md. Plugins count however they were composed. Contributor-only protocol files such as stage-definition.md are not loaded. SKILL.md files, the IDE conductor agent (agents/aidlc-aidlc.md), aidlc-common/conductor.md, and tools/, sensors/, hooks/, scopes/, and steering/ are loaded by the IDE or the engine, not through fs_read, and are not counted. A rule that hides only some of them is reported with a count and the framework folders it touches, for example hides 11 of 110 framework files (.kiro/agents/).

Global-source matches fail doctor. Project .gitignore and .kiroignore matches warn instead, because doctor cannot read the IDE setting that governs whether those workspace files apply.

<source> is a fixed name: ~/.config/git/ignore (or $XDG_CONFIG_HOME/git/ignore), core.excludesFile (run git config --get core.excludesFile for its path), ~/.kiro/settings/kiroignore, .gitignore, or .kiroignore. Doctor output is read by the agent, so doctor never prints an ignore file's path, its rules, or git's error text.

A source doctor cannot evaluate warns as not evaluated, and its fix: line names the way forward:

  • git is not available: put git on PATH and re-run doctor. Until then, check the named files by hand. Git's global excludes file is the core.excludesFile git reads, most specific first: command-scope settings in the environment (GIT_CONFIG_COUNT with GIT_CONFIG_KEY_<n> and GIT_CONFIG_VALUE_<n>, or GIT_CONFIG_PARAMETERS), the repository config (.git/config and .git/config.worktree; in a linked worktree or submodule, where .git is a file, the git directory its gitdir: line names and the directory that git directory's commondir file names), your global git config (~/.gitconfig, $XDG_CONFIG_HOME/git/config or ~/.config/git/config, or the file GIT_CONFIG_GLOBAL names), then the system gitconfig (the file GIT_CONFIG_SYSTEM names, else the system file of the git installation, such as /etc/gitconfig or etc/gitconfig under a Git for Windows install; skipped when GIT_CONFIG_NOSYSTEM is true). Follow each file's include.path and applicable includeIf.<condition>.path entries recursively. When none sets it, the file is $XDG_CONFIG_HOME/git/ignore, or ~/.config/git/ignore when XDG_CONFIG_HOME is unset.
  • git rev-parse exit <n> or git config exit <n>: git refuses this project even though a repository exists on disk. Run git status in the project to see why; for dubious ownership, run the git config --global --add safe.directory command git prints. Meanwhile, run git config --get core.excludesFile outside the project (in your home directory, for example) to find git's global excludes file (no output means $XDG_CONFIG_HOME/git/ignore, or ~/.config/git/ignore when XDG_CONFIG_HOME is unset) and check it.
  • Any other reason, such as a git command that did not finish (it timed out): check the named files by hand; git's global excludes file is the one git config --get core.excludesFile prints.

If GIT_CONFIG is set in your shell, clear it before running git config --get core.excludesFile, for example with env -u GIT_CONFIG git config --get core.excludesFile (in PowerShell, run Remove-Item Env:GIT_CONFIG first). GIT_CONFIG points only git config at another file, so the command would otherwise name a file git does not apply; doctor clears it the same way.

Remove or narrow the rule at the named line, then re-run /aidlc --doctor. Keep per-repo personal ignores in that repo's .git/info/exclude, which git honours and Kiro does not list as an ignore source. A negation in another file or a permissions allow is not a substitute for fixing the offending rule.


State File Issues

Symptom: Orchestrator reports corrupted state, or workflow behaves unexpectedly.

State file missing

The state file is created during Initialization or when a scope is provided to /aidlc.

  • Run /aidlc --status to confirm no workflow is active
  • Run /aidlc or /aidlc <scope> to start a fresh workflow

State file corrupted

The validate-state.ts hook checks for two required sections on every compaction: ## Stage Progress and ## Current Status. To repair:

  1. Run /aidlc --doctor and address any reported state, graph, or hook issues
  2. If the generated Stage Progress rows are stale, re-run the engine path that owns state resync: start or resume the workflow with /aidlc, or change scope through /aidlc --scope <scope> so the compiled graph and scope grid are reapplied
  3. Use .claude/knowledge/aidlc-shared/state-template.md only as the section and field contract; do not restore stage rows by hand from the template
  4. If the record cannot be repaired, retire it with /aidlc intent archive <name> (its record dir under aidlc/spaces/<space>/intents/ is preserved) and run /aidlc to start fresh

Dispatched Stage Timeouts

Symptom: A dispatched stage (Reverse Engineering, Practices Discovery, User Stories, or Code Generation) returns errors or truncated output.

What happens

The framework follows a built-in retry protocol:

  1. Automatic retry with a reduced-context prompt
  2. If retry fails, two options:
  3. Run inline — execute the stage directly in the main conversation (no subagent boundary)
  4. Skip and revisit — mark the stage incomplete and return later

Manual recovery

Re-run /aidlc: it detects the [-] (in-progress) state and carries on with the stage; say redo to run it again from the start. Check the audit/ shards for the error entry to understand what failed.


Approval Gate Stuck

Symptom: The workflow is waiting for your response at an approval gate.

How to proceed

Type your response when prompted. Options are:

  • Approve — continue to the next stage
  • Request Changes — provide feedback for revision

On Kiro IDE, if you already replied and the workflow still waits, see Kiro IDE hooks not running. On Kiro CLI, see Kiro CLI hooks not running.

Revision loop escape hatch

After 3 revision cycles on the same stage, a third option appears: Accept as-is. This archives the current version and moves on.

Skipping a stage

Use /aidlc --stage <target> to jump to a different stage. Intervening stages will be marked [S] (skipped) in the state file.

A reviewed document needs another change

If a final review already covers the document, direct edits are blocked so the review cannot silently certify different content.

  • While the stage is active or awaiting approval, describe the change and choose Request Changes. The decision can be recorded before the gate opens.
  • While the stage is [R], restart it with /aidlc --stage <slug>.
  • After the stage is [x], restore the reviewed source state or jump back with /aidlc --stage <slug> to redo it.

When only workspace source changed and the one recovery review is still available, start that recovery request before replacing the old Review section. The pending request temporarily permits writes only to that stage or Unit while the stale condition remains. Restoring the reviewed workspace source, recording the verdict, or starting/resuming another session re-arms the freeze. Restoring output-document bytes does not clear audit-recorded artifact staleness. After a session restart, retry the same pending request before replacing the Review section. The gate remains closed until the matching verdict is recorded.

A directory source manifest is refused because it contains ignored output

Symptom: A directory claim such as src/ answers with contains ignored application source "src/main.js.map" after a build.

Git ignore rules alone do not remove files from the review source boundary. For generated output outside that boundary, add its exact path (or its output directory) to exclude in the repo root's .aidlc-source-paths.json, for example {"version":1,"exclude":["src/main.js.map"]}, then retry the review. The directory claim can still cover the source beside it. A registered paths entry takes precedence over exclude, and other ignored files still inside the boundary retain the refusal. Exact-file claims must still name admissible source; an exclusion does not make ignored output review evidence.

An exact source-manifest file is refused because Git ignores it

Symptom: An exact file already listed in source-manifest.json answers with is ignored by Git and cannot be source-review evidence.

An ignored exact file is admitted when HEAD already tracks it or when it is explicitly registered as source. Adding it only to the Git index (including force-add) or tracking it with jj alone does not establish HEAD membership. For a file intended as reviewed source, merge a registration such as {"version":1,"paths":["src/runtime.js"]} into .aidlc-source-paths.json in that source repository's root, then retry the review. Keep existing entries. A registered path takes precedence over exclude. Files under folders AI-DLC never treats as source, such as node_modules/ or sensor caches, cannot be registered: omit their exact claims instead.

For output that is not source, omit the exact claim; use the registry's exclude list to leave the output outside the source boundary instead of registering it as source. Directory claims ending with / have a separate ignored-descendant check; exact-file admission does not change that check.

Code Generation cannot complete because files changed that no Unit covers

Symptom: Approving Code Generation answers with "N changes made during Code Generation that no Unit's review covers (...)".

Something changed in the workspace during the stage that no Unit's source manifest lists. The line names the three ways through, and the assistant takes the one that fits: the Unit that made the change lists the path and is reviewed once more; a change nobody meant is undone; a path that is not source (a tool's cache written inside the repo, a build output, a nested repository that is not this project's code) is left out of the source checks by naming it under exclude in .aidlc-source-paths.json (the file in that repo's own folder for a recorded repo). The exclude works at once, with no further review; remove the line to put the path back. A path the project's .gitignore already ignores is never counted. Under Guard Policy relaxed or off the change is kept and said once instead.

Plan Approval asked twice for the same plan

Symptom: Code Generation presents the Plan Approval question again for a plan you already approved.

Plan Approval binds to the plan, unit test instructions, and Testing Contract content, to the target, and to the current stage attempt. It is NOT reopened by re-running /aidlc, by a session restart or a context compaction, by a Stop-hook probe, or by /aidlc --status. Ticking a plan checkbox does not reopen it either, and recording a review never touches the plan.

For the same target and attempt, plan, test instruction, or Testing Contract edits reopen approval only under Guard Policy strict. Under relaxed or off, work continues with the updated content and the original approval record stays intact; it does not claim you approved the edits. The Guard Policy: line of /aidlc --status shows the effective setting. You can still ask to review the plan again.

If code generation starts without asking you about the plan at all, plan approval is off for this piece of work: status shows where that came from, for example Plan Approval: off (from scope poc). The line that names each plan asks whether you want to look at it first; you can also ask to be asked about every plan. See Plan approval.

Testing Posture, scope, test strategy, or project type changes follow the same rule within the same intent, target, and attempt. Refresh the current contract and instructions as needed; a lowered fence permits continued execution without asking for approval again solely because those inputs changed.

If you are asked again, check what changed and which rule applies:

  • the plan content or embedded Testing Contract while the plan-approval fence is on (beyond a ticked task marker, or a terminal ## Review section left by a review recorded before review records existed)
  • the unit-test instructions content, any byte of it: the instructions are handed to the developer in full, so they bind byte-exactly, and a section appended to them after approval reopens it when the plan-approval fence is on
  • the Testing Posture, scope, test strategy, or project type while the plan-approval fence is on
  • the active intent, Unit, or stage target
  • the stage attempt: a backward jump, a Request Changes, a gate rejection, or a workflow restart

The question names what it is about. Other code moving after approval (a git pull, another Unit landing) never asks again: the build continues and you hear which files moved. The exception is a build of Units in parallel under strict: a change after you approved (your edit or commit, a git pull) asks again before the Units are set up, and stops the next Unit from landing until you undo it or set Guard Policy relaxed (see Guard Policy). Nor does anything between your answer and the build: a long chat compacting its context, parking the work and resuming it, or another question coming up first. Say "review the plan" if you want to look again first, including right after any of those: the plan is shown for approval again before anything more is built.

Plan Approval is not recorded

Symptom: you answered the Plan Approval question, but AI-DLC shows it again.

Your answer counts from any chat on this piece of work, in your own words ("1", "approve", "looks good", "rename the handler"): the agent records the choice you made, with your words beside it. The question comes back only when the agent could not record a choice, most often because the reply arrived before the question was shown, or in a chat where the harness did not pass it to AI-DLC. Answer the question it shows. If it keeps coming back, run /aidlc --doctor: a harness whose prompt hook does not run cannot record any reply. A long chat that compacts its context while the question waits keeps the question open, so your answer still counts.

If AI-DLC says the project's files cannot all be read, or that the workspace source cannot be bound (a link that loops, a tree too large to read, or a source path outside the project), what happens depends on your settings. Under Guard Policy strict with plan approval on, the plan cannot be approved yet, because nothing could say what the build starts from. Otherwise the plan question is asked as usual (with plan approval off, the plan is built as written) and the build starts without a check of the project's files, with one line that says so. To have the files checked, repair the source boundary the message names (add the offending path to the exclude list in .aidlc-source-paths.json, which looks like {"version":1,"exclude":["<path>"]}, declare real source under an excluded directory in its paths list, or remove a broken symlink), then run /aidlc ($aidlc on Codex). /aidlc --doctor has a "Workspace source boundary binds" check that names the failing path and says which of these applies to you.

If the plan's Testing Contract is refused, the message names one of three causes: the block is missing, it is not valid JSON, or it changed after it was rendered. The repair is the same for all three: re-run render and replace the whole ## Testing Contract section. A changed block usually means a shell command rewrote the file and re-encoded its characters (for example PowerShell Set-Content); artifacts are edited with the file-editing tool instead. When your own edit broke the block, the assistant repairs it and asks you once to build the edited plan.

Legacy Kiro IDE windows. A Kiro IDE build that passes no typed text to AI-DLC approves plans with the picker only, through the older recorded decision and answer steps. There an answer binds to the chat session it was given in. When the project's files cannot be checked, you can still ask the assistant to build the plan anyway, by picking that or saying so, and it is recorded as your approval with no check of the files. Updating Kiro IDE lets you answer in your own words, from any chat, or edit the files.


A Bolt attempt was set aside — getting the files back

A recovery can set aside an attempt when its reviewed files changed again and its one allowed re-review was already used. The recovery abort's --discard saves tracked files and non-ignored untracked files (or the remaining branch tip when the checkout is already gone) plus reviewed source refs in local Git before removing the old checkout and branch, so a fresh attempt can start. An ordinary Abort without --discard leaves the checkout in place and returns parked_ref: null, with no parked_stamp, parked_mode, parked_repo, restore_operation, restore_hint, restore_hint_error, or parked_excludes. After a discard, the assistant tells you why it set the attempt aside and offers restoration only when restore_operation is present, regardless of whether a display hint could be rendered. Every successful abort retains reason: "aborted" and echoes the supplied --reason text in the additive abort_reason field. When an attempt was parked, the result includes the saved descriptor: parked_ref, parked_stamp, parked_mode (snapshot, branch-tip, or evidence-only), and parked_repo (null for the project root, otherwise the sibling repository name).

If files were saved, ask to restore them. The assistant uses the saved result's restore_operation: route worktree, args ["restore", "--slug", slug, "--parked", stamp, "--repo", repo ?? ".", "--intent", recordDirName, "--space", space] when the stamp is known. The final selectors pin the owning intent. It invokes the installed {{INVOKE}} engine worktree <args...> route with each listed arg exactly as a separate argv argument, never joined into a shell command. restore_hint is human display text only, not the assistant's execution input. The equivalent manual command, run from the main project checkout, is:

aidlc engine worktree restore --slug <slug> --parked <stamp> --repo <name|.> --intent <record-dir-name> --space <space>

The operation always includes --repo <name> for a sibling repository or --repo . for the root. Its optional display hint is safely rendered for the selected shell; a native install uses the prefix above, while a Bun-based copy install uses bun .claude/tools/aidlc-worktree.ts, substituting your harness directory. If safe rendering fails, for example because the harness directory is invalid, the result omits restore_hint and supplies restore_hint_error with the reason. The typed operation remains available; this does not mean that only evidence was saved or withdraw the restoration offer.

Do not drop the operation's exact stamp, repository, or owning intent selectors: without --parked, restore chooses the latest saved head. For manual invocation an exact stamp found in only one repository selects it before generic slug ambiguity; if selection is still ambiguous, use doctor's exact operation with --repo <name> or --repo . for the project root.

If a saved namespace is known but its discard descriptor is unavailable, the fallback retains parked_ref and derives parked_stamp from its namespace only when the stamp parses strictly; otherwise parked_stamp is null. It reports parked_mode: null and parked_repo: null and omits restore_operation, restore_hint, restore_hint_error, and parked_excludes, rather than guessing a repository, saved mode, or latest-attempt selection. Instead, recovery_hint asks you to run doctor to list set-aside attempts and their exact restore commands. The hint is plain guidance, not an executable operation. The assistant must not claim what files were saved or offer restoration from the fallback alone. If no namespace was saved, parked_ref is null; parked_stamp, parked_mode, parked_repo, restore_operation, restore_hint, restore_hint_error, parked_excludes, and recovery_hint are absent.

If only review evidence remained, discard reports parked_mode: "evidence-only" and parked_commit: "-". Abort keeps the ref, stamp, mode, and repository but omits restore_operation, restore_hint, restore_hint_error, and parked_excludes. The assistant says: "Nothing of its working files remained to save; only its review evidence was kept." It does not offer restoration. Selecting that attempt with restore, even with --raw, refuses with no restorable files were parked for <slug> <stamp>; only review evidence was kept.

After a successful restore, open the returned worktree_path, normally .aidlc/restored/bolt-<id8>_<slug>-<stamp> (the recorded legacy name for a pre-upgrade attempt). It is separate from any new live attempt; restoring files does not resume the old attempt or make its review current. This is local recovery, not a remote backup. If the old checkout was already gone, only its remaining branch tip and review evidence could be saved; if its branch was gone too, only review evidence could remain.

Limits depend on parked_mode: a snapshot reports parked_excludes: ["ignored files", "eol/text=auto normalization"]. Ignored untracked files are not saved (tracked files remain included), and normalization may change line endings while saving; normalized bytes cannot be recovered, even with --raw. A branch tip instead reports ["uncommitted files (no working tree existed)"], and the assistant says: "I kept its committed work; there were no uncommitted files to save." Snapshots restore stored blobs directly; branch tips use ordinary checkout conversions unless --raw is given. See the restore command reference for filter failures and raw recovery details.

Run /aidlc --doctor (or aidlc doctor) to find saved attempts. Its informational Parked attempts section lists slug, stamp, age, mode, restored-checkout presence, and typed recovery operations with exact --parked <stamp> and explicit --repo <name> or --repo . args, followed by owning --intent and --space selectors. Every JSON entry has purge_operation; only restorable entries have restore_operation. Each has route worktree and args to pass exactly as argv, never a shell command string. Optional restore_command and purge_command are safe human display text; if rendering fails, the corresponding command is omitted and restore_command_error or purge_command_error explains why, without removing the operation. Evidence-only entries have only the purge operation and its command-or-error fields. Impossible dates or times have age_days: null in JSON and show unknown in human-readable output. Saved attempts are not warnings or failures.

Doctor resolves namespaced attempts through their intent's registry UUID and legacy attempts through the exact WORKTREE_DISCARDED Parked ref provenance. Unknown or ambiguous owners and unattributed legacy parks are not listed. Once you no longer need one, remove any restored checkout first, then:

aidlc engine worktree purge --slug <slug> --parked <stamp> --repo <name|.> --intent <record-dir-name> --space <space>
aidlc engine worktree purge --slug <slug> --older-than 30 --repo <name|.> --intent <record-dir-name> --space <space>

Purge without either stamp selector removes every saved stamp for the selected intent's Bolt. --older-than accepts nonnegative finite days and selects strictly older UTC stamp timestamps, ignoring any -N suffix. The strict calendar parser rejects impossible dates and times rather than normalizing them. Age-filtered purge keeps unparseable stamps and reports them in skipped_unparseable. This JSON array is always present and otherwise empty; exact-stamp or all-stamp purge can remove unparseable stamps. --older-than cannot be combined with --parked. Purge refuses while a selected restored checkout exists, even if moved; it never removes a live Bolt checkout. Use the same Bun tool prefix for copy installs. See the purge reference.

Restore and purge reject unknown or duplicate flags before selecting or changing anything; use only the flags in the command reference. Recovery selectors and doctor accept the project root (.) and valid Git repositories named in the same slug's WORKTREE_CREATED or WORKTREE_DISCARDED audit Repo fields even when those sibling names are symlinks: the framework may recover exactly where it recorded the attempt's worktree or parking. This admission is slug-scoped; records for other slugs never widen this slug's repository set. Membership in a current or historical intent's repo list alone cannot admit a symlink. Intent-list candidates and unrecorded discovered siblings must be real immediate child directories whose canonical paths stay directly under the canonical workspace root (isWorkspaceRepoDir). Arbitrary paths and symlink aliases without same-slug audit provenance are refused. These recovery selectors do not change live create/discard commands or the required human consent.


Context Compaction

Symptom: Claude Code summarized earlier conversation context. The session may feel like it "forgot" recent discussion.

What is preserved

All record-dir artifacts, aidlc-state.md, the audit/ shards, and .aidlc-engine/recovery.md persist on disk. Only in-memory conversation context and partial in-progress work not yet written to files is lost.

How to recover

Run /aidlc after compaction. The framework:

  1. Reads aidlc-state.md to load workflow position
  2. Compares .aidlc-engine/recovery.md against the state file - warns if they differ
  3. Carries on where the work stopped

If the recovery breadcrumb warns about a mismatch, say "redo this stage" to safely re-execute the stage that was in progress during compaction.

The build stops after a compaction

Symptom (GitHub Copilot): you approved the code plan, the build started, and after the chat compacted every build step the assistant tries is refused.

Your approval, the workflow state, and every file already written are kept; only what the assistant had not yet written to a file is gone from the chat. After a compaction the assistant must read its step again before it builds anything. It runs next as its own command, which hands the approved build straight back without asking you again. /aidlc --doctor shows the step as out of date, with the time and the reason (the chat was compacted, or the workflow state changed after the step was issued, naming what changed when it is known), until that next runs.


Audit Log Growing Too Large

Symptom: this clone's audit shard has grown to thousands of lines over a long project.

A long project's shard is large by design; leave it where it is. The engine reads every shard in audit/ to know which stages you approved and which Units you finished, so moving one out of audit/ makes that work count as not done and the engine hands it out again. (The PreToolUse guard refuses the agent's file and shell tools any write into audit/.)

Git considerations

The audit/ shards are committed (not gitignored), see What to Commit vs. Gitignore. Each clone writes its own <host>-<clone>.md shard, so concurrent appends never merge-conflict.

Moved, copied, or synced projects

aidlc/.aidlc-clone-id records this clone's token and the host name it was first used on, so the shard name stays the same when the machine's name changes or the folder is copied or synced to another laptop: the work continues in one shard. A fresh git clone gets its own token and shard. Two copies of one folder are one clone, so if two people (or two laptops) work at the same time, give each its own git clone. If a sync tool leaves a conflict copy such as <host>-<clone> 2.md, AI-DLC reads the rows it shares with the original once, so finished work keeps counting and the copy can stay. With team Unit ownership, landing a Unit still stops on any file it did not expect, a copy included: it names the file (Unit landing requires a clean source worktree; commit or stash: ...).

If such a copy was already in your project on an earlier release and you kept working, Units you finished while the copy sat there may be handed out once more after you upgrade (the Units you finished before the copy count again). Nothing is deleted: the Unit's files are still there, so for most stages finishing it again only records it; a Code Generation Unit may ask you to approve its plan once more and build again from the code already in your branch. It happens once and never repeats, and a planned follow-up removes even that.

One narrow case: a Code Generation Unit built in its own worktree that had finished but was not yet merged when you upgraded. Building it again stops with Worktree directory already exists, or resume requires the completed, merged prior Bolt. Run aidlc engine worktree discard --slug <unit>: it sets the earlier attempt's files aside before it removes that worktree, then the next /aidlc builds the Unit again, and aidlc engine worktree restore --slug <unit> brings the earlier files back into a separate checkout whenever you want them.


Lock Files Left Behind

Symptom: Hooks appear to hang briefly then skip. Subsequent audit entries are not written.

The audit hooks use mkdir-based locking (via lib.ts) to prevent concurrent writes. If a hook is interrupted, the lock directory may persist. Lock files are created in the system temp directory (os.tmpdir() -- typically /tmp/ on macOS/Linux, %TEMP% on Windows).

Finding stale locks

# macOS / Linux
ls -la /tmp/.aidlc-*

# Windows (PowerShell)
Get-ChildItem $env:TEMP -Filter ".aidlc-*"

Lock directories are named .aidlc-audit-<hash>.lock and .aidlc-subagent-<hash>.lock inside the system temp directory.

Clearing stale locks

Run /aidlc --doctor first. It automatically clears only a provably-dead generation, a reused PID whose creation generation no longer matches, or an old lock whose owner stamp is genuinely missing. Matching/unknown live generations, malformed stamps, and unreadable stamps are reported but not removed.

Before any manual cleanup, stop all AI-DLC processes using the affected locks, confirm ownership and that the projects are quiescent, and preserve diagnostic evidence. Investigate only the named lock; do not bulk-delete lock directories. Locks and their owner-stamped .reap recovery gates are transient and recreated as needed. .gate-mutex files are persistent advisory-lock anchors and may remain empty in the temp directory; an empty file is not evidence of a stale owner. Project transaction locks use the ownership checks above.


Statusline Issues

Shows "ready" when workflow is active

The statusline reads the **Lifecycle Phase** field from aidlc-state.md. If that field is missing or empty, it falls back to [AIDLC] ready.

Fix: Run /aidlc --doctor to check state file integrity. Verify the ## Current Status section contains a **Lifecycle Phase** entry.

Shows stale data

Expected behavior — the statusline updates when the state file is next written, typically at stage transitions.

Not appearing at all

  1. AI-DLC's status line shows only when you chose it at setup or turned it on: run /aidlc --statusline on ($aidlc --statusline on on Codex). On Claude Code it goes into your own .claude/settings.local.json; a status line your organization's managed settings choose still wins.
  2. Run aidlc doctor and repair the reported native command or host wiring.
  3. On a copy install, verify Bun is on the host process PATH.
  4. With no state file, [AIDLC] ready is the expected output.

Using --doctor

The --doctor utility command validates your setup. Run it whenever something seems wrong:

/aidlc --doctor

It checks: prerequisite (bun), hook availability (every framework hook wired by settings.json must exist in .claude/hooks/, and a wired-but-missing hook fails loudly; a valid custom non-AI-DLC statusLine intentionally exempts the unwired aidlc-statusline.ts), hooks-not-globally-disabled (a resolved disableAllHooks: true in any Claude Code settings layer fails loudly), managed project-hook policy (allowManagedHooksOnly: true), project structure (settings.json), workspace shell readiness (.claude/ + aidlc/spaces/default/memory/), state/audit consistency (the workflow Status against a recorded WORKFLOW_COMPLETED, and each Stage Progress checkbox against the stage starts and completions the audit recorded for the current attempt. A stage the audit shows as started whose checkbox still reads [ ] is what makes the workflow refuse to finish it, and the warning names the exact line to change. Under team Unit Ownership the per-unit Construction checkboxes are derived from Unit Progress, so they are not compared), hook heartbeats, graph integrity (no cycles, every graph entry has a file), the Composed plugin surface (enabled plugin stages are compiled; contribution sidecars and targets are valid; recorded structural additions and prose fragments remain present and unchanged), selection-aware plugin-authored checks, scope validation across all 11 scopes, Composed scope durability (every composer-authored scope resolves to a real plan: a scope file with no grid column, a durable aidlc/scopes/<name>.md record not yet projected, or a runnable workflow naming an unresolvable scope all fail, with graph compile as the remedy wherever compile can reach the cause; a missing column with no record behind it is reported apart, since compile emits a column only for a scope some stage declares), stage schema + graph references, and keyword overlap across scopes. Passing advisory rows include Duplicate producers for consumed artifacts whose producer is ambiguous by graph load order, Rule drift (with lifecycle-stale overlaps reported separately as stale-suppressed), Paired sensor coverage, stage/gate ledgers with no HUMAN_TURN, approval gates waiting for a human for more than 24 hours, plugin advisory checks, uncommitted workspace records, fresh in-flight compose/background-subagent state, and, when repos.json exists, declared-repo and managed-.gitignore drift. A compose marker older than 24 hours or background-subagent entry older than 2 hours fails with the exact rm aidlc/.aidlc-* remediation; doctor never deletes either surface. Hook drops is conditional: a hook that silently degraded (e.g. a plugin compose that could not apply a contribution, or a failed recompile) records a severity-tagged line to <hooks-health>/<hook>.drops; a [degraded] drop fails doctor (so a CI gate catches a half-applied plugin), while any other drop is a passing row naming each hook's most frequent reasons (each up to its first colon; the detail stays in the file), raised to a Hook failures, the latest within the last day warning while the hook's latest failure is under 24 hours old (it clears a day later or when you delete the file; an [advisory] line never raises it). A hook's normal decisions, such as the Stop hook letting a turn end because you have to answer first, go to <hook>.trace and are never counted. The plugin compose hook rewrites its drops file each run, so fixing the cause and re-composing self-clears it. Clean and warnings-only reports exit 0; any failed check exits 1. Healthy rows collapse by section unless --verbose is present, while every warning and failure remains visible. The report writes to stdout either way. Core checks are read-only: on a fresh shell with no intent yet they create nothing, so the command is safe to run before the first intent is created. Plugin checks execute installed plugin code that is required by convention to be read-only, but the runtime cannot enforce that property. Once an intent exists doctor records a HEALTH_CHECKED (and GUARDRAIL_LOADED) audit row.

On Kiro IDE, it also checks each ignore source independently for rules hiding .kiro/, naming the file and line. Global-source matches fail; workspace-source matches warn because kiroAgent.agentIgnoreFiles governs whether they apply. See Kiro IDE Read Denials. On every harness but Cursor it also warns "AIDLC hooks have not run in this project yet" when no AI-DLC hook has run in the project. That is expected before your first chat message; after one, its fix names your tool's step (see, for example, Kiro IDE hooks not running or GitHub Copilot hooks not running). On Kiro CLI, a workflow whose hooks never ran fails "Hooks have never executed" with the engine its hooks need; see Kiro CLI hooks not running.

The Workspace record visibility advisory, beside the uncommitted-records row, catches user ignore rules added after config. It names the rule's file, line, and hidden committed record paths; narrow the rule rather than force-adding individual records. This warning does not change doctor's exit code. The row is absent when the records are visible, outside a Git repository, or when Git is unavailable.

On Claude Code, doctor also reads the machine-managed managed-settings.json and alphabetical managed-settings.d/ fragments. If the effective allowManagedHooksOnly value is true, organization policy blocks every hook declared by the project's .claude/settings.json; only your Claude Code administrator can lift that policy. When that policy is not set and heartbeats are still absent after workflow progress, set "disableAllHooks": false in this project's .claude/settings.local.json; it works in the same chat. When a workflow has issues, --doctor also prints a Workflow diagnosis section listing structured findings (unresolved gates, a stale or missing runtime graph, cold hooks, and similar "it will not advance" causes) — the same analysis --doctor --export writes to its report.

See CLI Commands for full details on what each check validates and how to fix failures.


Sharing a Diagnostic Report

When a workflow is stuck or misbehaving — a gate that will not open, a stage that will not advance, an approved report repeatedly refused — and you want a maintainer to look, run:

/aidlc --doctor --export

This runs a fresh --doctor pass, then writes a small, redacted diagnostic report to aidlc/diagnostics/ (override with --output <dir>). It packages a timestamped .tar.gz when a system tar is available; otherwise it keeps the report directory and tells you to compress it yourself. Share that archive (or directory) — it carries the diagnosis and redacted evidence, not your work product. No workspace source, raw state/audit/runtime-graph files, or artifact/contribution/question/memory bodies are included; paths are normalized, intent ids are hashed, and secret-like values are scrubbed.

The report reconstructs the workflow timeline from the audit trail and runs deterministic condition→remedy rules. The two most common causes it catches:

  • Unresolved approval gates — a stage whose gate never resolved is the single most common "it will not advance" cause.
  • Stale or missing runtime graph / cold hooks — a runtime graph older than its authored inputs (or absent), or a hook that has not fired in a long time, points at a recompile that did not run.

report.md inside the report lists every finding with a remedy; a remedy that names a recovery bypass (such as an AIDLC_DISABLE_* env var) is flagged as not safe to automate. See CLI Commands for the full report contents and safety model.


Next Steps