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
Windows: the audit or another record shows — for — and → for → The file is UTF-8, and Windows PowerShell 5.1 read it as ANSI. Read it with Get-Content -Encoding UTF8, or use PowerShell 7. A file rewritten from that reading keeps the wrong characters, so copy a record with Copy-Item or Explorer, and share a run with /aidlc --doctor --export
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 or Kiro CLI v3: deny fs_read matching ".kiro/" Run /aidlc --doctor; remove the .kiro/ rule from the ignore file it names (see Kiro 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 CLI: AI-DLC's reviews and helpers do not run, and the agent says it has no tool to hand work to Kiro CLI's Workflows feature is on. Ask the agent to turn it off, or run aidlc config trust --kiro-cli-workflows off --yes, then quit Kiro CLI and start kiro-cli --v3 again in this project (see Kiro's Workflows feature)
Kiro IDE on Windows, Kiro's terminal is Command Prompt: command results end at an AI-DLC reply: line or are cut off after it and steps take extra turns, or every command shows exit code -1 Ask the agent to set Kiro's terminal to PowerShell, or run aidlc config trust --kiro-terminal powershell --yes, then restart Kiro (see Command Prompt as Kiro's terminal)
Kiro IDE on Windows, Kiro's terminal is PowerShell: every command shows exit code -1 although the folder is trusted, and results end at an AI-DLC reply: line or are cut off Kiro's shell integration did not load, for example because PowerShell's execution policy is Restricted or AllSigned; aidlc doctor run in Kiro's terminal (not /aidlc --doctor in the chat, which cannot see it) names the cause in its Kiro terminal row. In Kiro's PowerShell terminal (Windows PowerShell and PowerShell 7 keep separate policies) run Get-ExecutionPolicy -List and $ExecutionContext.SessionState.LanguageMode; when MachinePolicy or UserPolicy is set, or the language mode is not FullLanguage, ask your IT team; when Process is set, start Kiro from the Start menu; when the policy in effect comes from CurrentUser or LocalMachine and is Restricted or AllSigned, run Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned there and restart Kiro. Kiro's terminal.integrated.shellIntegration.enabled turned off, or a PowerShell profile with extra arguments, has the same symptom (see PowerShell without Kiro's shell integration)
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 --v3 again in the folder (when it asks to trust the folder and you know what is in it, choose Trust, continue) (see Kiro IDE hooks not running)
Kiro IDE or Kiro CLI: an approval says your answer was not recorded because aidlc-record-human-turn is switched off, or the next AI-DLC step says an AI-DLC hook is switched off That hook's file in .kiro/hooks/ carries "enabled": false: Kiro IDE's Agent Hooks panel writes it, and a file committed that way brings it to every clone. AI-DLC never turns it back on for you. In Kiro IDE turn it back on under Agent Hooks; in Kiro CLI change "enabled": false to true in the file the line names, then quit Kiro and start kiro-cli --v3 again in the folder (hook files are read when a session starts) (see A Kiro hook switched off)
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 CLI (V2) needs Kiro CLI's v2 engine (kiro-cli --v2), or v3 once Kiro has upgraded its agent files; Kiro needs v3 (kiro-cli --v3) (see Kiro CLI hooks not running)
AI-DLC says its knowledge base cannot read files in your knowledge documents folder, or aidlc doctor warns about them Those files were never added to the knowledge base, or have no text it can read. Do what the line says for each one (add it, or save a .md, .txt or .csv copy beside it), then run /aidlc knowledge sync (see Document Knowledge)
aidlc doctor says this project is in a synced folder (Google Drive, OneDrive, Dropbox, Box or iCloud Drive), or a review or plan approval is refused for a file nobody edited The sync client can rewrite files AI-DLC checks, and a changed file stops an approval until it is reviewed again. Move the project out of the synced folder, or pause sync for it, then take the step the refusal names
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
A program is watching the project folder (most likely a dev server or a test watcher still running) (Windows) A program that watches every folder of the project, such as a dev server (Vite) or a test watcher left running, keeps AI-DLC from moving the lock folder of its work record, so each step waits about 10 seconds. Stop that program (stopping npm run dev may stop only npm and leave the server running: close it from Task Manager or with taskkill /T /PID <pid>), and the next step goes on as normal. When the assistant, or an agent it sent, started that program in the conversation (to check the app, say), it stops it and the work goes on: you see this line only when neither started one, or the stop did not free the folder. With Guard Policy strict the build's writes are refused until it stops.
Windows: git says Filename too long for a file under aidlc/, or a review or questions file cannot be written The project folder is too deep: without long paths turned on, Windows tools and Git refuse paths over 260 characters, and AI-DLC's records sit deep under the project folder. aidlc config says so in one line, and aidlc doctor shows a Project folder row with how deep the folder is and how much the records add. Move the project to a shorter folder (for example C:\src\<name>), or turn long paths on: as an administrator, run New-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem -Name LongPathsEnabled -Value 1 -PropertyType DWORD -Force in PowerShell, then run git config --global core.longpaths true. AI-DLC reads these two settings and says nothing when both are on; it never changes them, your folder or your git settings. Copilot CLI asks before every read of a path over 260 characters (copilot -p refuses it), whatever these two settings say, so with Copilot CLI only a shorter folder takes those questions away, and the line is said either way.
Workflow stuck or misbehaving, need help Run /aidlc --doctor --export and share the produced .tar.gz (redacted; no work product). To also cover what only your AI tool's own chat log shows (refusals, repeated questions, approvals), ask for an issue report with /aidlc-issue-report (Codex: $aidlc-issue-report): the run's records and the tool's events with names and text replaced by labels, checked before you send them; doctor's findings are in it, the archive itself is not sent (run /aidlc --doctor --export again if the team asks for it)
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.exe" 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 finds aidlc.exe in the bin directory (normally %LOCALAPPDATA%\aidlc\bin) but never aidlc.cmd. An install from before aidlc.exe has an extensionless aidlc launcher beside aidlc.cmd instead, so the bare name resolves in these shells; if neither is there, rerun the installer or aidlc use <version> (from PowerShell or CMD, where aidlc already resolves) to write aidlc.exe. 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 exits 4 or the Windows active pointer is invalid The launcher (aidlc.exe or aidlc.cmd in bin) 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.
On Windows, aidlc-shim.ps1 cannot be loaded or is not digitally signed, or the installer, aidlc update, aidlc use or aidlc rollback stops with an error that begins command pointer validation failed for <version>: version probe returned 1 "" A Group Policy execution policy overrides the -ExecutionPolicy Bypass that aidlc.cmd passes, so PowerShell refuses the launcher before it runs. A release whose activation checks the new version through aidlc.cmd then undoes the activation: the previous version stays active, and after a first install none is. Run Get-ExecutionPolicy -List: the first row from the top that is not Undefined is the policy in effect, so MachinePolicy comes before UserPolicy. When that row is MachinePolicy or UserPolicy and reads AllSigned or Restricted, it is the cause; RemoteSigned and Unrestricted let the launcher run. 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.exe" uninstall, or the recorded aidlc.cmd when aidlc.exe and aidlc.cmd in bin are not both as AI-DLC installed them, 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.
the last AI-DLC uninstall is still finishing Windows removes AI-DLC's files after aidlc uninstall ends: under a minute for one or two installed versions, longer for more or on a slower machine. Nothing was changed; run the installer again when the line says. A cleanup that stopped without finishing is started again by the first AI-DLC command other than doctor ten minutes after it began.
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 Kiro CLI (V2) 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 CLI (V2) and Kiro also share .kiro, but aidlc config --harness kiro (or --harness kiro-v2) switches an installed one to the other in place (from Kiro CLI (V2) to Kiro without a terminal, or under --quiet or --json, add --yes); 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 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 no longer match this switch's plan means what the switch reviewed changed after that review; run the --dry-run again and review what it names.
cannot switch .kiro to kiro: .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 command is still working in <project>. Another AI-DLC command (another chat, tool or terminal on this project) holds it. Wait for it to finish, then run your command again. If it repeats while nothing else runs, follow Transaction lock ownership.
an AI-DLC command on another computer ... is working in <project> ... or left its lock there., or .../.aidlc-transaction.lock cannot be read. The lock was left by another computer that shares the folder (or by this one before it restarted), or it cannot be read. If no AI-DLC command is running there, delete the folder the line names, then run your command again; see 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.
Cannot create an AI-DLC transaction lock or Cannot use the filesystem at ... during config The project's storage lacks an operation AI-DLC needs. See Config fails with a storage 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.

Config fails with a storage error

AI-DLC makes no hard links. Its project lock is an owner-stamped .aidlc-transaction.lock folder, and it puts a file at a name only when nothing is there, by an exclusive create and a rename, so exFAT drives, network shares and WSL /mnt/c need nothing extra. 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. A scripted aidlc config --harness <name> runs no probe of its own: on storage that cannot rename files it stops at the first rename with the same Cannot use the filesystem at ... line and fix, rolls back, and leaves only the empty folder it had made. Passing probes cannot certify atomicity or crash durability. See the capabilities and support matrix in Transactions and Recovery. An S3 mount name or a storage 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 lock this computer stamped before it restarted is cleared the same way, since its owner stopped with that boot. A lock whose owner stamp never finished (no owner.json, an empty one, or one cut off before it reads as JSON) is what a command stopped while taking the lock leaves; within its first few seconds it reads as another command still working, and after that the next command clears it. A live owner is retained. So is a lock stamped by another computer that shares the folder, or by a release that recorded no computer and boot, since a PID absent here is not proof that its owner stopped; and so is a stamp that reads but names no valid owner. Those two say which folder to delete once nothing is running there.

For manual diagnosis, preserve the error, lock, and named staging/recovery paths. Inspect .aidlc-transaction.lock/owner.json (the lock file itself for a file lock an older release left), and establish the owner process, computer, and mount history with the operator. Commands on one computer must share its PID namespace (two containers with one hostname do not). Stop writers before corrective work and retain the evidence while ownership is uncertain. Do not delete the project lock or its local coordination gate to make a retry proceed while an AI-DLC command may still be running.


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 CLI (V2) distribution (--harness kiro-v2, .kiro/agents/aidlc.json): hooks run on Kiro CLI's v2 engine, so start it with kiro-cli --v2 (Kiro CLI 2.21.4 or later; for an older one, see Kiro CLI (V2) prerequisites), with the aidlc agent active. v3 does not run the file as AI-DLC ships it, but runs it once Kiro has upgraded it, which Kiro CLI 2.37 and later does by itself at a start on v3 unless chat.enableAutoAgentUpgrade is false in your Kiro CLI settings (it keeps each original as <name>.json.bak; see Kiro CLI (V2) usage). With another agent picked, type /agent and pick aidlc, then carry on in the same chat. If aidlc is not in that list (Kiro says agent "aidlc" needs upgrading for this agent engine when it starts), the session is on v3 with the files not upgraded: type /upgrade-agent, choose the workspace agents, then quit Kiro and start kiro-cli --v3 again in this folder; or switch to Kiro (below) with aidlc config --harness kiro; or quit Kiro and start it again in this folder with kiro-cli --v2 --agent aidlc. From an ACP client, start kiro-cli acp --agent-engine v2.
  • Kiro distribution (--harness kiro, .kiro/hooks/aidlc-*.json): hooks run only on Kiro CLI's v3 engine, so start it with kiro-cli --v3. Kiro CLI 2.33.0 takes the engine only from the command line or your own Kiro CLI settings: it ignores the "chat.agentEngine": "v3" that .kiro/settings/cli.json ships (and refuses kiro-cli settings --workspace chat.agentEngine), which only Kiro CLI 2.24.1 to 2.32.x read. 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 CLI (V2) 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 Code or Codex started in a folder inside the project

Both tools offer /aidlc ($aidlc in Codex) from a folder inside the project, such as src/, but AI-DLC's hooks work only when the tool is started in the project folder itself: Claude Code runs none of the project's hooks there, and Codex runs them from that folder, where they cannot start. No setting and no /hooks trust changes that. When the tool's own record of the chat says it was started in such a folder, the agent changes nothing and shows one line: exit the tool, start it again in the project folder, and type the /aidlc --request <id> line it showed you, which carries on with your request once. Doctor gives the same step. To find where the chat started, AI-DLC reads that record and nothing else in it: on Claude Code sessions/<pid>.json in its config folder (CLAUDE_CONFIG_DIR, else ~/.claude), on Codex the first line of the chat's file under sessions/ in its home (CODEX_HOME, else ~/.codex). With no such record the usual step for hooks that are not running stands.

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

Kiro IDE 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/; a file committed that way switches the hook off in every clone, in Kiro CLI too, which has no such panel. 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. In Kiro IDE, turn the hook back on under Agent Hooks. In Kiro CLI, change "enabled": false to true in the file doctor names, then quit Kiro and start kiro-cli --v3 again in the folder: Kiro reads the hook files when a session starts. 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 these steps rather than to trust the folder; nothing turns a hook back on for you.


Kiro Read Denials

Kiro IDE or Kiro CLI v3 denies every read under .kiro/ ("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 CLI v3 says it as:

Blocked by a permission rule (deny fs_read matching ".kiro/"); the user did not reject it. Source: ~/.config/git/ignore.

Kiro IDE and Kiro CLI v3 honour git's global excludes file (in git repositories) and ~/.kiro/settings/kiroignore automatically. Kiro CLI v3 also applies the project .kiroignore, and not .gitignore. In Kiro IDE, workspace ignore files apply only when its kiroAgent.agentIgnoreFiles setting names them (the default includes .gitignore; [] disables workspace sources). Kiro 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 a Kiro IDE or Kiro CLI v3 install (.kiro/agents/aidlc-aidlc.md present), it reports the offending source as:

Kiro 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 conductor agent (agents/aidlc-aidlc.md), aidlc-common/conductor.md, and tools/, sensors/, hooks/, scopes/, and steering/ are loaded by Kiro itself 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 tell which Kiro you run, and cannot read the IDE setting that governs whether those workspace files apply in Kiro IDE. The warning says where each applies: Kiro CLI v3 applies .kiroignore, so there a .kiroignore match denies those reads, and does not apply .gitignore.

<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 approves the stage as it is and moves on. AI-DLC keeps the count in its record of the work, so the option still appears after you stop and resume, or continue in a new chat.

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 its own folder for a recorded repo or a recorded checkout). 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, and neither is a file another open piece of work in this folder lists in its own Units' source manifests (a second chat building its own work here), or anything under a folder it lists: that is the other work's change, and its own checks cover it. Archiving a piece of work you will not finish (/aidlc intent archive <name>) ends its claims. Under Guard Policy relaxed or off the change is kept and said once instead.

On a plan with no Units the same change answers with "the project source changed after reviewed it" (or, once the one recovery review is used, "changed again after the one recovery review"), followed by what changed and the same way through for a path that is not source. The exclude works there at once too, with no further review.

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 says you can ask to go over it at any time; 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 (a Testing Posture change made after the build's review, such as a testing practice you keep at the learnings step, applies from the next plan and does not reopen approval for that build)
  • 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.

A valid Git checkout kept inside the project can share its object store with jj, including through a linked worktree. If an older AI-DLC install reports "no resolvable HEAD commit" for a commit that Git can read from a jj-created pack, update AI-DLC and refresh the project's install. Repacking the repository or changing jj settings is unnecessary. A genuinely missing or unreadable HEAD object still needs repair.

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 and the audit/ shards 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. Carries on where the work stopped

To have the stage that was in progress done again, say "redo this stage".

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 never finished (missing, empty, or cut off). Matching or unknown live generations, stamps that name no valid owner, 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 and Kiro CLI v3, 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 doctor cannot tell which Kiro you run: Kiro IDE's kiroAgent.agentIgnoreFiles governs whether they apply there, and Kiro CLI v3 applies .kiroignore but not .gitignore. See Kiro 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 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 and Unit names 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.
  • Missing runtime graph / cold hooks: a runtime graph that is absent, or a hook that last fired more than a day before the newest stage or approval step recorded on the intent, points at a recompile that did not run. Opening a chat, a prompt and doctor's own audit rows are not counted as work, so an intent nobody is working on does not read as having cold hooks.

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