# paqad-ai

## 1.128.1

### Patch Changes

- 3ccd469: The release job that publishes the discovery plugin now runs on Ubuntu 24.04, where Python 3.9 is available, so the plugin reaches `Eliyce/paqad-product-discovery-plugin` again.

## 1.128.0

### Minor Changes

- ac990a6: The discovery plugin now installs from `Eliyce/paqad-product-discovery-plugin` in Claude Desktop and in Codex (`codex plugin marketplace add Eliyce/paqad-product-discovery-plugin`), with no hooks, so Claude shows no "runs code" warning. Every release publishes it at the paqad-ai version. It ships only discover and ask; refining, sizing and sprint planning stay in the paqad plugin.

  The skills already publish as `discover`, `ask` and `start`; only the plugin name changes, from `paqad-product-discovery` to `paqad`. Commands move from `/paqad-product-discovery:discover`, `/paqad-product-discovery:ask` and `/paqad-product-discovery:start` to `/paqad:discover`, `/paqad:ask` and `/paqad:start`.

  Install this plugin or the paqad plugin, not both: both are named `paqad`. `paqad-ai doctor` fails, and `paqad-ai update` and `paqad-ai install` warn, when both are installed.

  Step 0 now finds the Jira project from the repository's branch names and commit subjects, and asks when they do not point to one; it never searches Jira broadly. Discovery reads the business docs first, then the code, and never the technical notes; `refine-ticket` and `size-work` in the paqad plugin read the same way, business docs then code. When both the code and the tickets are read, the playback opens by showing where they agree and differ, and the code and docs win.

## 1.127.0

### Minor Changes

- 20eb078: The HUD no longer binds to the home folder, follows the session when its folder changes, and says when it cannot find the session's record. `paqad-ai doctor` warns when the home folder is set up as a paqad project. `paqad-ai status --verdict` prints the session verdict, the Stop hook holds a closing message whose verdict word differs from it once, and the band shows closed changes, marked stages and repeated stages honestly. The task list drops Load rules so it matches the band.

## 1.126.0

### Minor Changes

- 1575d0d: The discover journey can now work from Jira. With a repository connected it reads the repository first and the tickets second; with only Jira connected it grounds the idea on existing epics and tickets instead of stopping. Ticket-based lines say "the tickets say" with their keys, a ticket marked done is never told as built, and when the repository and the tickets disagree the repository wins and the disagreement is shown. Reading stays inside one project, with at most 25 tickets looked at and 10 opened in a run, and never touches comments, attachments, work logs or people's names. At the decide step the product owner can put the new tickets under an epic that already exists in Jira; that epic is checked first and never created, edited, labelled or moved, and a new `plan_posting.py resume` checks it again after a break. The glossary also learns terms from tickets, and replies follow the language the person writes in. `ask`, `refine-ticket`, `size-work` and `plan-sprint` do not read Jira as a source. The privacy text now says what is read from the tracker.

## 1.125.0

### Minor Changes

- f1b7a4f: Add the rules discovery workflow. Say "discover rules" and paqad lists the packages the project uses, turns settled decisions and sourced research into rule ideas, merges them with your existing rules into one proposal you sign off, then writes the rules, tags the decisions and refreshes the stack docs. New verbs live under `paqad-ai rules discovery` (`start`, `status`, `decisions`, `research`, `propose`, `review`, `sign-off`, `apply`, `docs`) beside `paqad-ai rules inventory`. The full rule reset is removed: `paqad-ai refresh --rules` and `--force` and the dashboard "Refresh the rules" action are gone; onboarding still copies the default rules once.

## 1.124.0

### Minor Changes

- f0f4bec: The Desktop HUD strip says more in less room, counts changed lines from the first edit, and shows design sign-off.

  - The header reads `Feature`, keeps the cost on the right and drops the cost, then the lane, then
    the workflow when the band is narrow. The flag mark and words are one control.
  - The strip shows only the working stages. High Table is a fixed 150 px and Delivery a fixed
    190 px; narrow bands hide High Table first, then Delivery. Delivery is two lines of text: the
    state (`Not pushed`, `PR #823 · CI running`) and the commits and line figures.
  - The HUD snapshot gains `ship.diff`: lines added and removed by the change, counted from local git
    before any PR exists, new files included.
  - When design sign-off applies, a `Sign-off` stage sits between Spec and Build with coloured
    status words and a `Check`, `View` or `Copy design` button. `paqad-ai hld check-approval` now
    records when it last ran.

## 1.123.1

### Patch Changes

- 11d8c28: Feature work now shows as feature work from the first message.

  A prompt like "develop issue 830, do not create a PR" no longer routes to a question, and any message that starts with "develop" counts as a code request, the same as "add" and "fix". The first prompt of a session now tells the agent how the hook routed it, so a wrong guess gets corrected, and opening a change moves the session to feature development.

  While no change is open yet, the Desktop HUD shows `Paqad Getting Ready` with every stage grey instead of an empty band or a Question pill. The terminal says the same on one line. A leftover turn from an earlier message no longer blanks the band.

  A change is now judged only on its own files. Rule and duplication findings in files it never touched no longer fail it, and a change with no edits at all is no longer held at the end of a turn. A change that has done real work is still judged in full.

## 1.123.0

### Minor Changes

- 9d980f3: A decision pause can now suggest an earlier answer that a person approves in one click, and every outcome is logged.

  - When an agent opens a question with `paqad-ai decision create`, it sees the titles of the earlier questions, whatever their wording, because agents word questions themselves. It reads up to 5 with `paqad-ai decision check <id> --read <D-id> ...` and judges whether an earlier answer still fits. It must record its finding with `paqad-ai decision suggest` before `decision resolve` will run. The Approvals screen is exempt, because a person answers there directly.
  - The title list stays under 24,000 characters and 200 rows, newest first, and `older_omitted` says how many older answers were left out. Only listed answers can be read or suggested. The list of offered ids is removed when the question resolves.
  - Questions opened by automated callers keep their word match, so one with no match opens as before. `.paqad/decisions/index.json` also works as before.
  - The suggested answer comes first, as `Same as last time: <label> (from D-...)`, then the other options and, when it fits within four choices, `Always use this answer for this kind of question`. A question from an automated caller takes only its listed options, so `--other` is refused there, and a fifth option is listed under `not_shown` with its command.
  - `paqad-ai decision resolve <id> <key> --always` keeps a standing answer in the tracked `.paqad/decisions/standing-answers.json`. Commit that file with the resolved question. The answer applies to the whole team once merged and lasts until `paqad-ai decision standing remove <id>`. `--ask-anyway` on `decision create` asks this one time. Nine sensitive kinds of question can never have a standing answer, and a stage agent cannot set or remove one.
  - Nothing is answered for you when a decision pause opens, except by a standing answer a person chose. Older reuse that runs before a pause is unchanged, including spec questions answered from a close precedent, which are now logged.
  - The `paqad.decision-reuse` ledger records each suggestion, standing answer and auto-answer, and the receipt can show a line such as `decisions: 3 earlier answers suggested, 2 accepted, 1 changed; 1 standing answer used`.
  - The `decision` skill now covers the whole flow.

## 1.122.0

### Minor Changes

- 37e95fb: Teams can now ask for a short design sign-off before the build starts, posted where the team already works.

  - A new team file, `.paqad/configs/git-workflow/design-sign-off.yaml`, turns it on. It is off by default, so nothing changes until a team opts in, and `paqad-ai update` adds the file with its defaults.
  - After the spec is frozen on a listed lane, paqad asks for a high-level design in plain business language. The new `high-level-design` skill writes it and `paqad-ai hld check` checks its length, its sections, and that it has no code words, jargon or em dashes.
  - The agent posts it with the tools it already has in the chat, with no setup in paqad. The tracker comes from the ticket the developer pasted (a Jira, GitHub, Linear or ServiceNow link), and otherwise from `tickets.yaml`. The approval channel can differ from the tracker, for example Jira for tickets and MS Teams or Slack for sign-off, and it is the tracker when the team names none. Guides cover Jira, MS Teams, Slack and GitHub.
  - With `wait_for_approval` on, the first code edit waits for sign-off. `paqad-ai hld check-approval` reads the replies: a teammate's approval or the approved ticket status opens the gate, a clear request for changes sends the spec back, and anything else keeps it waiting. The developer's own replies, bots, negated approvals and replies from before the latest version never count.
  - `paqad-ai hld skip --reason` builds before sign-off when the team allows it, and the skip is posted back to the team. When the destination isn't connected, the design is shown in chat and the change carries on.
  - A new chat lists the designs still waiting, and a prompt naming a waiting ticket picks that change up again. The pull request body and the receipt say whether the design was signed off.

## 1.121.1

### Patch Changes

- 2aec415: The plugin ships a smaller package manifest and no type files, and its search engines install at exact versions.

  - The plugin's `package.json` is now generated with only the keys it needs, and the tree no longer carries `.d.ts` files from its build.
  - The optional search engines install at the exact versions the release was built with, from a script you can read at `runtime/scripts/install-engine.mjs`. Provider API keys are not passed to npm, and failures land in the install log.
  - On Windows that install now starts npm through Node, with no shell. This has not been run on Windows yet.
  - Assembled scripts no longer hold a raw 0x7F byte.
  - Allow once now starts the plugin's own program, not a global `paqad-ai`. If that program is missing, nothing is recorded and the edit stays blocked. On a Windows root it starts `paqad-ai.cmd`, which has not been run yet; if that start fails, the edit stays blocked.
  - The README says what the HUD does with your prompt, and what the engine install runs and leaves unfixed.
  - A number in a branch name no longer counts as a GitHub ticket unless it sits where the branch template puts the ticket, so `fix/round-5` no longer asks its PR to link `#5` or puts it in a commit message.

## 1.121.0

### Minor Changes

- 60d947f: Stage agents now follow one recipe and prove it, and the ledger records what they really reported.

  - The record now reads each stage's real report, whether the agent handed it back or ended in plain text. A stage that says it finished without its result is sent back, up to three times, then recorded as blocked with the reason.
  - `paqad-ai stage report <agent_id>` tells the main chat what a stage reported and what to do next, and the next stage refuses to start past a stage that stopped.
  - `paqad-ai stage begin <stage>` starts a stage in one command and prints what it needs, so a stage takes fewer turns.
  - The stage ledger gains a lock, a hash chain and duplicate protection. The chain catches accidents and silent loss, not someone who rewrites the file on purpose, and it cannot see rows cut from the end.
  - Each stage gets its recipe at start. Its stage command checks the recipe's script, and the end-of-change check asks each new stage for that proof. On Codex the recipe is written to the project, kept out of git, and read rather than injected.
  - Agent files are short and each do-not line names what enforces it. Plugin and npm installs now render the same failure policy on the edit gates.
  - On the plugin route the three edit gates now block when their hook cannot run (`onFailure: block`, measured on Claude Code 2.1.302). If a partial install or a missing `node` blocks every Edit and Write, run `/plugin update`, which needs no edit, and try again.
  - `paqad-ai stage repair <row> --reason <text>` records why a ledger row broke the chain, and the end-of-change check accepts a row repaired that way.
  - The rule check before an edit no longer refuses an edit that only removes a finding. If the edit takes at least one finding out of its file and adds none, it passes and is recorded, and any other findings still block at the end of the turn. This does not apply on Windows or under `rule_gate_pre_edit=all`.
  - When an agent draft asks for risky powers, `agent test` waits on one approval decision for that exact file. If the file changes while the decision is unanswered, the old decision is discarded and a new one is raised for the file as it is now.
  - The Ledger shows recipe, report and turns per stage, and the receipt states turns against the budget.

## 1.120.0

### Minor Changes

- 20b9724: Clean up what the last update left behind, and stop team files changing on updates.

  Team files now hold `schema_version: 1` instead of a paqad version, and update rewrites one only for a migration, a retired value or setting, or a stale workflow entry. A new setting no longer appears as a comment in them: find it in `.paqad/.config.example` or with `paqad-ai config show`. `.paqad/.config.example` and `.paqad/hook.mjs` no longer hold a version, so they change only when their content does.

  The first update swaps the line once. One person updates and commits the swap, then teammates update. Everyone needs this version or newer, including the plugin inside sessions, because a lagging plugin binary comes first on the PATH there.

  These 11 settings are removed, because nothing read them: `research_depth`, `full_lane_default`, `require_adversarial_review`, `block_on_stale_docs`, `require_db_review_for_migrations`, `escalate_destructive_operations`, `escalate_risky_migrations`, `escalate_security_findings`, `escalate_db_row_threshold`, `decisions_max_screens_per_task` and `decisions_idle_timeout_minutes`. Update removes a live line once and says so. `feature-development/safety.yaml` goes with them, so update deletes it, or keeps it and says so when it holds notes your team wrote.

  Also fixed:

  - Update repairs the kept rule lines that point at deleted files, and names any line your team wrote.
  - Doctor accepts `ai_attribution` in `commits.yaml`, and no longer reports `commits.yaml` as changed outside the skill right after the first update.
  - Update and doctor give the exact lines to add when your hooks folder is tracked. The check is skipped in a terminal where `paqad-ai` is not on the PATH.
  - The stub left in `.config.app` has the corrected text and no empty heading.
  - Update recompiles stale rules, and `paqad-ai rag refresh-context` does so whatever the route. A failed refresh exits non-zero.
  - Doctor checks entry files only for providers the project uses, and warns when the running `paqad-ai` is older than the repo.
  - `paqad-ai config effective` names the real reader for every setting.

## 1.119.0

### Minor Changes

- cc69e40: A background update now tells you what it changed. It leaves a git-ignored record, and the session after the update adds one line asking the agent to tell you. Run `paqad-ai update --last` to see the same summary and notes a manual `update` prints. This line reaches Claude Code and Codex developers only for now. The session that starts the update doesn't hear about it, because the update runs in the background.

  `Changed <n> files:` in the `update` summary now counts every file the update changed, not only the regenerated ones.

### Patch Changes

- cc69e40: `paqad-ai doctor` no longer fails the detection report and manifest checks on `node-cli`, `node-library` and `node-service` projects. When one of those checks does fail, it now names the field and value, such as `detected_stack: not-a-stack isn't an allowed value`.
- cc69e40: `paqad-ai update` no longer pins paqad's own old stage instructions into `feature-development/workflow.yaml`. It removes any instruction or read path paqad once shipped for that stage, including `docs/modules/**` and `docs/instructions/**`, and prints one line for each. Only the line goes, never a file or folder, and anything paqad never shipped stays. To keep a removed line, reword it, because the same wording is removed again on the next update. Commit the file afterwards so teammates don't repeat the change.

  `update` also drops deleted paqad files from the onboarding manifest and lists `ai_attribution` as commented lines in `git-workflow/commits.yaml`.

- cc69e40: `paqad-ai update` now prints a short summary instead of a JSON report that could run past 100 KB. Run `paqad-ai update --json` for the full report. It also leaves a file alone when its content wouldn't change, so a run no longer lists unchanged files or makes a running session reload the framework.

  A team that had set `evidence_existence_gate=strict` no longer gets an invalid `legacy_existence_check: strict` from the move to YAML. The value now becomes `warn`, and your next `paqad-ai update` fixes a file that already holds `strict` and tells you it did.

  This release also refreshes the committed rule-binding lock, which was out of date on the last release and blocked edits on a clean checkout until it was refreshed.

## 1.118.0

### Minor Changes

- c59a28c: paqad no longer writes a copy of the feature-development workflow to `docs/instructions/workflows/feature-development.yaml`, and no longer writes editor schemas to `.paqad/configs/schemas/` or a `# yaml-language-server` line at the top of each team file. paqad reads your settings straight from `.paqad/configs/`.

  Your first `paqad-ai update` (or `paqad-ai join` on a teammate's machine) removes what older versions left behind and prints one line for each thing it removed: the workflow copy, its hash file, its line in `.git/info/exclude`, the `docs/instructions/workflows/` folder when nothing else is in it, the schemas folder, and the first schema line of each team file. Nothing else in your team files changes, and your own workflow files in that folder stay.

  `paqad-ai config view` is gone. To see every setting and its value, run `paqad-ai config show`, or read the table in `.paqad/configs/README.md`. Stage agents now get their instructions in their brief; `paqad-ai stage brief <stage> --full` prints all of them when a brief was shortened.

- c59a28c: Every team file under .paqad/configs/ now lists every setting it can hold, commented out with paqad's default and a one-line note. Remove the `#` in front of a setting (and its group name) to change it; a setting left commented out keeps paqad's default, so a better default in a later version still reaches you.

  Expect a one-time change in all 13 files on your first `paqad-ai update`: it rewrites each file in this layout and names every file it rewrote. Your values and your comments are kept, a setting paqad doesn't know moves under a "Not a paqad setting" line, and other notes move to a notes section at the end. The setting notes were also rewritten in plain language.

- c59a28c: The pentest, site-map, design-test and codebase-health workflows now ship as skills, each with a Retest mode, instead of seven rule files copied into your project. `paqad-ai update` removes the old copies you never changed and tells you about any you edited, which it keeps.

## 1.117.0

### Minor Changes

- 30bdc06: Move delivery rules to .paqad/configs/git-workflow/, add the git-workflow skill that owns them, and make paqad follow and check them for agents and people.

  The five files (`tickets.yaml`, `branches.yaml`, `commits.yaml`, `pull-requests.yaml` and `enforcement.yaml`) replace `docs/instructions/workflows/delivery-policy.yaml`, which `paqad-ai update` migrates once and deletes. `paqad-ai deliver` follows every setting, the end-of-turn check and the commit-msg and pre-push hooks check the rules, the dashboard's Git workflow page edits one file per tab, and `paqad-ai doctor` reports problems in a new `git-workflow` check. Ask your agent to change the rules through the git-workflow skill.

- 30bdc06: Move team settings from .paqad/configs/.config.* and the feature-development workflow file to readable YAML files under .paqad/configs/, with automatic migration.

### Patch Changes

- 30bdc06: The committed team launcher (`.paqad/hook.mjs`) now stands down only when the paqad plugin has claimed the session, not when it is merely installed. Before, the first Claude Code session after the plugin was installed ran with no paqad checks at all, because the plugin only loads in the next session. Run `paqad-ai update` and commit the refreshed launcher.
- 30bdc06: In a repo that commits the paqad plugin in `.claude/settings.json`, the plugin move's off-switches now work and `paqad-ai doctor` tells the truth. Doctor says `plugin (turned on by this project)` when the plugin loads there, instead of `npm`. `paqad-ai plugin rollback` turns the plugin off for you only, in the git-ignored `.claude/settings.local.json`, instead of saying the plugin was removed while it still loads. The background move skips the user-scope install where the project already turns the plugin on, and every install path now writes a line to `plugin-migration.log`. A team that sets `claude_install_mode=settings` in its tracked `.paqad/configs` file no longer gets the plugin keys written back into the shared settings on `update`.
- 30bdc06: Fixing a missing feature title no longer splits a change in two. The end-of-turn check used to advise `stage start planning --title`, which opened a second, near-empty bundle and paused the one holding the plan, spec and review, and the HUD then said Safe to merge for the empty one. Now `stage start --title` names an untitled active change in place, a new `paqad-ai feature title "<title>"` names it without touching the stages (and is what the check now suggests), and a turn that judges an empty bundle while the same session has unfinished work in another one reads Inconclusive and names both.
- 30bdc06: `paqad-ai update` no longer asks the onboarding questions when you run it in a terminal. It used to ask for your providers, stack and RAG choice as if the project were new, and the answers decided which files it wrote, so a wrong pick could write another stack's rules or change the adapter. It now reads the providers the project was set up with and asks nothing. Onboarding saves every provider in `.paqad/onboarding-manifest.json` under `providers`, and `update` works them out from your entry files (`CLAUDE.md`, `AGENTS.md`, `GEMINI.md` and the rest) when an older manifest has no list. `update` also refreshes every provider's files now, not only Claude Code's. `paqad-ai onboard` still asks in a terminal.

## 1.116.0

### Minor Changes

- 4d2ae59: Audit paqad's own skills and agents against the skill and agent lints. `paqad-ai skill lint --all` and `paqad-ai agent lint --all` lint the whole project into one deterministic JSON report (`--report`, `--group-by rule|folder`, `--as-of`), list persona files apart, and lint the stage-agent templates after rendering them. `agent lint --all --owner-powers-as-warnings` reports the owner-permission rules (AG-015, AG-018, AG-022) as warnings, so CI blocks on every other agent finding while the permission packets and the authoring completion gate keep enforcing those three. `paqad-ai skill audit` renders `docs/instructions/tech-debt/skill-agent-audit.md` with a kept Before section and a rewritten After section. paqad's custom skill keys move under `metadata`, with JSON-shaped values in a sibling `skill.meta.yaml`; skills that still carry the old top-level keys keep working through a parser fallback that is removed in 1.117.0, and the workflow router records one deprecation line per such skill and warns once.

  On Claude Code, paqad's stage agents come from the paqad plugin, and with team setup on (the default) the repo also commits the 8 agents in `.claude/agents/`, because a cloud session loads no plugin but does load committed agents. The copy in `~/.claude/agents/` is written only when the plugin really loads (a version 2 plugin list entry for this repo that is not switched off). With team setup off, onboarding and update remove old `paqad-*` agent files from `.claude/agents/` only when their content matches an agent file paqad generated, keeping any file you edited by hand and any symlink. **Behaviour change:** a Claude Code session with none of the plugin agents, the repo copies or the home copy now shows a "stage agents are missing" message and stops instead of running a stage in the main session. The orchestrator dispatches `paqad:paqad-<name>` and falls back to `paqad-<name>`; a stage reply with no Status line advances only when its stage ended with its artifact, is resumed once when it did not, and red checks never advance. Each stage agent's record now also says how it returned (`report_status`, `report_stated`, `advance`) and lists any broken must-not rule (asking the human, writing into a feature bundle, editing outside its stage). The `dashboard`, `join`, `onboard` and `start` skills run only when you call them. Every skill script answers `--help`. A new guard stops read-only stage agents from writing files through Bash, Edit or Write anywhere except paqad's temp folders (High Table seats only in their own), and denies writes it cannot place or that come from an unknown paqad agent. `paqad-ai skill test` now asks contract tests of the same scripts SK-010 lints, skipping `scripts/README.md` and helpers listed under Not entry points, and skill folder hashes ignore Python bytecode caches and `.DS_Store`. Skill draft keeps file modes, and releasing a paqad runtime skill in place copies nothing and refuses if the folder changed after the draft.

## 1.115.0

### Minor Changes

- b87c7f4: Add the Agent Orchestrator: a new or edited agent (a subagent file, a paqad stage agent or an expert persona) now goes through nine gated `paqad-ai agent` stages, from justify to release, with an agent lint, hook script tests, task-based evals with pass^k, a delegation test, host and SDK forms, tracked evidence and an `agent-<name>.json` bundle record that the end-of-change check requires. The `agent-orchestrator` seat joins the High Table, the QA expert gives a spec-compliance and a quality verdict, `paqad-ai spec pipeline experts benchmark` measures the High Table form, a delegation hook logs agent calls, and Claude Code projects are offered a cheap-tier `Explore` override.

## 1.114.0

### Minor Changes

- 4cfaf12: Teammates and Claude Code cloud sessions now get paqad straight from the repo, with nothing to install by hand. `paqad-ai onboard` and `paqad-ai update` write a shared `.claude/settings.json` (the paqad plugin offer plus the hook chain routed through a small committed launcher, `.paqad/hook.mjs`) and the stage helpers in `.claude/agents/`, and name the files to commit. The launcher steps aside when the paqad plugin is installed, forwards to an npm install when there is one, and otherwise sets up its own copy of the latest plugin on the first session and keeps it fresh, so stages and checks run the same for everyone and exactly one hook chain acts. Anything personal in an untracked `.claude/settings.json` moves to the git-ignored `.claude/settings.local.json`. In cloud sessions RAG is off, pull requests open, get comments and read checks through GitHub's REST API when GraphQL is refused, and the receipt says when evidence starts in the cloud. Set `team_bootstrap_enabled=false` to turn the team setup off; the next update removes what paqad wrote and keeps your npm hooks in `.claude/settings.local.json`.

## 1.113.1

### Patch Changes

- ab12948: `git status` is clean again after a session. Hooks write lock and marker files under `.paqad/locks/`, and that folder was not in the list paqad keeps in `.paqad/.gitignore`, so every session left it untracked. Fresh onboarding now ignores `locks/`, and `paqad-ai update` adds it to existing repos.
- ab12948: A change that was closed at the end of a turn and then reopened is now checked again when the turn ends. Before, the session that reopened it was treated as owning no change, so the final check was skipped, the change stayed open, and the dashboard verdict and receipt kept the first result. Only the session that reopened the change owns it; other sessions still never pick up a closed change. Also, a code request that lists its steps ("build, review and docs sync, checks") is no longer routed to the documentation workflow because of the words "docs sync". A request with no code words still routes "documentation sync" to the documentation workflow.

## 1.113.0

### Minor Changes

- 81e5bfe: New skills now have to prove themselves before they are added. When a change creates or edits a skill, the Skill Orchestrator sits at the High Table (a fast-lane change is raised to graduated so the seat is always called), and the development stage runs `paqad-ai skill` through nine gated stages: justify against three no-skill runs, intake, evidence with an overlap check, draft with a trace for every instruction, a deterministic lint (SK-001 to SK-019) plus contract tests in the project's own test framework, evals against a baseline on the project's fast and reasoning models, a trigger test, and release with tracked evidence. The end-of-change check now says "Needs your attention" when a new or edited skill has no passing or overridden record; a removed skill gets no check. You are only asked business questions (overlap, a risky script, a gap in the intake, an improvement, a retirement, an override), and a skill that cannot pass a gate is recorded as paqad's defect instead. On Claude Code a new PostToolUse hook logs when a skill fires, for `paqad-ai skill catalog`. Edits under `runtime/base/skills/**` in the paqad repository are gated the same way. Set `skill_orchestrator_enabled=false` to turn all of it off.

## 1.112.1

### Patch Changes

- 61a76ae: Releases are faster and no less checked. `npm publish` no longer runs the whole test suite again inside Actions: the release first proves that the 4 required CI checks passed on a tree identical to the one being published, and refuses to publish otherwise. A publish from anywhere else still runs `pnpm run ci` in full. The plugin is pushed as soon as changesets publishes, without waiting for npm to list the version, and every `npm view` now asks the registry for a fresh answer. A version-only release PR, and a push to `main` whose files match a PR that just passed, skip the test matrix only when that proof holds; anything else runs it in full. The slowest test file is split into four.

## 1.112.0

### Minor Changes

- 2962e9c: `paqad-ai checks run` now reuses a green build and test run when the files are exactly the same: the newest real run of each exact command must have passed on the same tree, lockfile, Node version and build output, otherwise everything runs for real (`--no-reuse` always does). Format and lint still run every time, and format runs on just the changed files when the pack can prove it is the same formatter. The completion gate now reads a checks report written for different files as Inconclusive, the speed report counts reused runs apart, and hand edits into `.paqad/checks` are refused.

## 1.111.0

### Minor Changes

- 2a7b1a8: Small changes cost less paqad time. The graduated lane now runs every stage in one agent, with the same six stages, artifacts and gates, and only the full lane uses a separate helper per stage. The new `stage_isolation_lanes` setting picks which lanes do (default `full`, and full is always included). At `plan compile`, a full lane the classifier guessed can drop to graduated once, before the spec starts, when the plan touches 8 files or fewer, none sensitive, with no schema or breaking API change. One line says why, and the change report shows it. If the change later grows past 8 files or touches a sensitive path, the lane goes back to full for the stages still to run. A lane set with `paqad-ai lane set` is never lowered. On graduated, the expert panel seats only the on-call experts the change needs, and always the security expert when a sensitive path is planned; `spec_pipeline_experts_lanes` (default `full`) controls this. To keep the old behaviour, set both to `graduated,full`.

## 1.110.4

### Patch Changes

- abe5a0d: The Desktop band shows one subagent line on the shared left edge, in the gap line's place, so the card stays the same height and never shows an empty row or a system reminder. The terminal band also keeps one subagent line. A light passes across the headline while work is running, and stops when reduced motion is on. The High Table shows up to three seats, the ones at work first, then `+N` and the chief. On a narrow band it shows two, so the initials no longer overlap. The README names Eliyce at the top.

## 1.110.3

### Patch Changes

- 3e4c161: The plugin directory no longer blocks the paqad plugin with "couldn't confirm that the mod leaves a permission decision with the user". The directory accepts no plugin hook that reads Claude Code's permission answer, so the HUD no longer has one. Two small things change:

  - While Claude Code's own permission dialog is open, the band no longer says "Waiting for your answer". It still says it for a pending paqad decision and for a question in the chat.
  - After **Allow once**, an edit that is denied again is recorded as "still blocked", without saying whether you refused the dialog or another rule blocked it.

## 1.110.2

### Patch Changes

- eabd759: The HUD now says Done, in green, as soon as paqad's work on a change is done: every stage finished, checks green and a verdict on record. It no longer waits for a commit, a push or a pull request. While the pull request's CI runs it reads "Coding Done: Watching CI". CI failing on the pull request's current head still turns the headline red, and a green run brings Done back. paqad's own record gaps show as a quiet note instead of holding Done back, and a change that loaded its rules no longer shows a false "could not record that the rules were loaded" note.

  The headline stays on one line, cut with "…" to the band width. It reads "Waiting for your answer" whenever a decision for this change is pending, or the chat is asking you something or waiting for a permission.

  While a subagent or background task runs, the band shows "Subagent:" and its task, with a calm breathing light, up to two lines of what it is doing (newest on top), and how many subagents finished on this change. With nothing running the normal headline comes back.

  The delivery rail now follows your push and CI by itself. Push is marked when your branch's upstream or the pull request head matches your latest commit. While an open pull request's CI is pending, the HUD runs a new read-only command, `paqad-ai delivery-link refresh`, every 30 seconds for at most an hour, with your own `gh` login. If it stops early, the note says why: time limit, offline or signed out. A new push starts it again.

  Merging is yours, so the HUD no longer shows a Merge step, a ready glow, a "Safe to merge" headline or a merged note. The receipt's verdict words and the delivery policy are unchanged.

  Finished stages now turn green with a check mark, and the stage strip glows green once, for about two seconds, when the last stage finishes. Reopening the HUD never replays it, and reduced motion turns it off.

## 1.110.1

### Patch Changes

- 4aea924: The HUD mod passes the Claude plugin directory check again: no name spelled like a hook parameter is bound outside the hooks, and a test keeps it that way. A new session no longer takes over a change that another session is running a stage in. A bare `stage start` then stops, names that change and the running stage, and tells you to pass `--title` to open your own change. When you switch branches, the change from the other branch is set aside instead of receiving your rows, and it is picked up again when you switch back. A change whose pull request was merged, including a squash merge, now closes as done at the next session start, unless a stage is still running in it. The HUD quiet line, which tells the agent to skip its stage lines, only appears when the HUD actually shows a change.
- 4aea924: Stage agents are recorded as started again in projects that have both the npm install and the Claude Code plugin. While the project's own settings still run the npm hooks, `paqad-ai update` now keeps those hook lines current instead of skipping them, so a newer hook such as the stage agent start reaches the project. The start hook also writes a line to the hooks log saying why it stood down, and a test checks that every hook the plugin ships has its npm counterpart.

## 1.110.0

### Minor Changes

- 2f40538: After development, review and documentation sync now run at the same time, and checks runs once on the final tree. On Claude Code the orchestrator dispatches the two agents in one message; on Codex it spawns both and waits on both. A review fix goes through the one development agent after both have returned, documentation sync runs again only when the fix changes what the docs describe, and then checks runs. Hosts without parallel subagents and the fast lane keep review, then documentation sync, then checks. A stage agent's start no longer releases another stage agent's hold, so the turn end keeps waiting for review while documentation sync starts and finishes beside it. Review runs `paqad-ai review digest` again just before it records, so documentation sync's edits are included, and returns blocked when that run fails.

### Patch Changes

- 2f40538: Allow once now works on every Claude Code plan, including Team and Enterprise logins and machines with Claude Code managed settings. The HUD never changes a permission answer any more: after you pick **Allow once, recorded**, it records the override and runs the same edit again, and paqad's own gate asks Claude Code to show its permission dialog for that one edit. A deny from your settings rules, another tool's hook or a rule your organization enforces still blocks it. A second line in the change's evidence now says whether the allowed edit landed, was refused or stayed blocked (`paqad-ai rules override --outcome`). The plugin also no longer ships `dist/plugin/` or raw control bytes in its bundled files, which the plugin directory flagged.

## 1.109.0

### Minor Changes

- 6130c70: paqad can be listed in Anthropic's Claude plugin directory, and a full-lane change spends less time starting agents. The HUD's permission hook now reads Claude Code's answer itself and never hands it on, so the directory can prove the decision stays with you; the one program it starts, its two files, its chime and its commands are written out where the directory reads them, and the README says what each one does. The OpenAI and Cohere keys can be saved as sensitive plugin options; a saved key wins over the environment, which wins over the project file. On a host that can resume a subagent, the planning agent carries on as the specification stage and one development agent serves the whole change, resumed for each next task, with the new `paqad-ai stage brief <stage>` printing a resumed agent's brief. `spec pipeline start` runs in the foreground and returns within 20 seconds: it grounds on the docs alone when the index is empty, no embedding key is set or retrieval runs past `spec_grounding_budget_ms` (default 15000), and it reuses its grounding for the same request.

## 1.108.0

### Minor Changes

- 96e34a0: paqad now asks the owner once per change. When expert claims fit together, the chief architect rules them compatible and writes one merged claim instead of turning them into a question, and the same disagreement is never asked twice. Planning no longer stops to ask which module a change belongs to: a confident choice (score 0.5 or more) is applied and shown to you as a choice you can change, and an unsure one waits for the spec questions step through a new `defer` escalation. The module attribution, the fix proof method and the visual-evidence readiness question all join one round at that step, listed by the new `paqad-ai spec pipeline round`, asked up to 4 at a time. A pending question now holds up only its own change, so other changes keep moving. A project that sets `attribution_pending: stop` keeps the old behaviour.

## 1.107.0

### Minor Changes

- 45eef15: New `paqad-ai report speed` shows where each change's time went, from the stage ledger and the Claude Code session transcripts: busy time, the part owned by development, by the other stages and by the main agent alone, time spent waiting on a person, the edit gate's median and p90 latency with refused edits by reason, and whole-suite versus targeted test runs, then totals per lane and the five biggest categories of busy time. Use `--change <id>` for one change, `--since <date>` to start at a date, and `--json` for machines. It only reads, never prints prompt or tool text, and shows a "no transcript" row when a change's transcripts are gone.
- 45eef15: Edits no longer wait for every rule script or get refused when the check times out. Before an Edit or Write, paqad now runs only the rule scripts that can block (deterministic, changed-files), several at a time, and a script marked `// per_file: true` re-checks only the files that changed since its last run. Every other script still runs at the end of the turn, and every blocking rule still blocks. The pre-edit check has its own time budget, `rule_gate_budget_ms` (default 6000, counted from the start of the hook, 500 to 9000): when it runs out, the scripts still running are stopped, the edit goes ahead with a note to the model, and the same checks run at the end of the turn and block there if anything fails. Two more knobs sit next to it in `.paqad/configs/.config.policy`: `rule_gate_pre_edit` (`blocking-only` by default, or `all` to run every script before an edit as before) and `rule_gate_concurrency` (`auto` by default, or a number up to 8; `1` runs them one after another). The hook timeout is unchanged.

### Patch Changes

- 45eef15: Stage agents are no longer sent back to reload the whole framework when paqad writes a rule, the rule-script map, a registry or a tech-debt item. The entry gate now goes stale only when the entry file, `.paqad/framework-path.txt` or a file under `docs/instructions/stack`, `design-system` or `workflows` changes. When one of those instruction files changed, the block names the changed files (up to 10, then "and N more") and asks the agent to read only those, write its marker and retry; a missing marker or a changed entry file still asks for the full load. Every entry-gate block now adds one line to `.paqad/logs/hooks.log` with the reason, the agent or session id and the number of changed files. Rule changes are caught by the rules-loaded gate instead: `paqad-ai rules load` now records a sha256 of each rule file it loaded, and an edit after one of those files changed is refused with a request to run `paqad-ai rules load` again. Records written before this release are checked for existence only.
- 45eef15: The background RAG refresh now runs only when it can help. Task notifications, stage-agent hand-backs and `Stop hook feedback:` prompts no longer start one; a human prompt starts at most one every 2 minutes. Only one `rag refresh-context` runs at a time: it holds `.paqad/locks/refresh-context.lock` for its whole run, renews it while it runs and releases it when it ends or crashes. The refresh runs at low priority, syncs the index once instead of twice, and a CLI command loads the local embedding model once instead of once per retrieval. Each refresh start adds one line to `.paqad/logs/hooks.log`. File discovery compiles each ignore-file, include and exclude glob once per refresh instead of once per file, which takes a refresh of this repository from several minutes of CPU to under half a minute; the same files are indexed as before.

## 1.106.0

### Minor Changes

- 7400def: The paqad plugin now ships the product-owner skills. Start with `/paqad:start` and say what you want, or go straight to `/paqad:ask` to ask what the product does today, `/paqad:discover` to shape an idea into ready tickets, `/paqad:refine-ticket`, `/paqad:size-work` or `/paqad:plan-sprint`. They work in claude.ai chat, Cowork and Claude Code, reading your project docs and code through a connector, uploaded files or the open folder. Every skill now says where it works: `/paqad:onboard`, `/paqad:join` and `/paqad:dashboard` need Claude Code with a project folder open, and in chat they say so in one sentence. The npm package does not carry the product-owner skills; they come with the plugin.

## 1.105.4

### Patch Changes

- 8fdfbb3: The HUD no longer says "Needs your attention" when nothing needs you. While a stage runs in a live stage agent, the running stage stays the headline even if a verdict was written meanwhile. A fail verdict with no failing check the Ledger can name now reads Inconclusive with its reason, never the bare words. The agent's end-of-turn summary carries no verdict word while a stage still runs in the background, and says nothing is needed from you.

## 1.105.3

### Patch Changes

- 6ca6ab7: The HUD now tells the truth while a change is still running. A change is no longer marked failed while one of its stage helpers is still working in the background, or in the quiet gap between two stages. The band keeps the same height, only asks for your permission when a prompt is really waiting on you, and keeps showing your change while a stage runs. Finished stages read Done with a green check, the Record only lists this change, each High Table seat shows one token figure, and flags appear only once their stage has ended. Changed files are now counted from where your change actually started, so earlier work on the branch and files from a merged base branch are no longer counted as yours.

## 1.105.2

### Patch Changes

- 71b3f4f: The HUD tells the truth about your change. The headline climbs from Done to Committed, PR open, Safe to merge (only on real CI green) and Merged. The Trust tab shows the proof stage by stage and keeps paqad's own record gaps apart from problems in your work. A finished change stays on screen with its result, a stage mark after a close returns to your own change, and the turn no longer ends while your checks are still running.

## 1.105.1

### Patch Changes

- 7bab5bf: The HUD's rule stop no longer approves an edit itself. When you choose "Allow once, recorded", paqad still records your override with `paqad-ai rules override`, and then hands the edit to Claude Code's own permission step, which shows its dialog or follows your permission mode. The HUD now keeps every use of the mod API inside its one hooks file, which clears the two blocking findings from Anthropic's plugin directory. The README says what the HUD reads, writes, runs and sends.
- 65df660: Add a repeatable benchmark for the paqad plugin, built on `claude plugin eval`. Three suites run inside real Claude Code sessions, each case once with paqad and once without, against a small fixture project: routing (did the request reach the right workflow), firewall (was a rule-breaking edit stopped, while allowed edits still land) and receipt (did the final message carry an honest verdict). A weekly and on-demand GitHub workflow runs them and fails when the routing or firewall score with paqad drops below 0.9. Nothing in the installed package changes; the suites live in `evals/` and are not published.
- d0847ee: The prompt router now sends more everyday phrasings to the right workflow. "run a security review" goes to pentest, "audit the UI against the design system" to design-test, "map the app's surfaces, navigation and journeys" to site-map, "analyze which of our rules can become scripts" to rules-analyze, and a rough idea you want help shaping goes to discovery instead of being read as a question. A request that names a source file and says what to change in it, such as a refactor or "make X fall back to Y", is now treated as a code change.

## 1.105.0

### Minor Changes

- 5e85255: The HUD now tells what is really happening. "Needs you" shows only while a question is on screen, a permission waits for you, or a decision is pending, and it clears when you answer. A rule that stopped an edit no longer asks for you; it stays in the Ledger as history, and answering "Let Claude fix it" closes it. Expert-conflict and near-copy decisions that block every edit now show in the band. The fast lane is Plan, Build, Checks: it no longer requires Spec, Review or Docs, and its strips draw only those three. Build, Checks and Docs are recorded whenever an edit touches them, in any order, so a root `SECURITY.md` edit no longer drops every later Build and Checks edit. The Edit step stays current while files are being edited, a failure from an earlier turn no longer leads while Claude works, and info-level hints no longer raise a flag. The feature card appears only once a change starts, and the router no longer reads "implement-ready" or "style" as a code change. Coral now means waiting on you; flags and marked stages use a new amber.

### Patch Changes

- 5e85255: The npm package is much smaller: about 9 MB unpacked instead of 69 MB, and a 2.4 MB download instead of 15 MB. It no longer ships source maps, and the bundles share their common code instead of each carrying a copy. The dashboard finds its files the same way from any build layout. Each release now waits up to 15 minutes for npm to list the new version before it decides whether to publish the Claude Code plugin, so the plugin no longer falls behind npm.

## 1.104.1

### Patch Changes

- 8795daf: The Claude Code plugin is ready for Anthropic's plugin directory. The plugin tree leaves out source maps and OS junk files, so no file is over the directory's 5 MiB limit. It now ships an icon and the security policy. `plugin.json` carries the listing data: display name, author, homepage, repository, license, keywords, icon, and links to the docs, support, privacy policy and terms. The README now says what paqad runs, writes and sends, and has a two-minute way to try it. Security reports go to security@eliyce.com.

## 1.104.0

### Minor Changes

- 2301192: Security fixes for the packages paqad-ai installs, and the Voyage embedding provider is removed.

  - The local search engine now uses `@huggingface/transformers` v4 (still pinned to the q8 model, so existing indexes keep working), and `fast-uri` moves to a patched release. Installing this version picks up every fix for the shipped packages.
  - The Voyage embedding provider is removed. If your project still has `voyageai` saved as its embedding provider (in `rag_embedding_provider`, `PAQAD_RAG_EMBEDDING_PROVIDER` or the project profile), RAG now stops with a message instead of guessing. Switch to `local` or `openai`, for example with `paqad-ai rag init --provider local`, and the index is rebuilt for the new provider. The `voyageai` package is no longer needed, so you can uninstall it, and a saved `VOYAGE_API_KEY` is no longer read.
  - Claude plugin users get their local search engine upgraded automatically the next time paqad runs.
  - CI now runs `pnpm audit --prod --audit-level high`. The braces advisory GHSA-vfj7-8cjw-p6xm has no patched release, so the audit ignores that one advisory by its id. Reason: braces is only reached through fast-glob, and paqad expands only glob patterns that come from its own code and shipped stack packs, plus one set built from the project's own files: code-knowledge entry points read from the project's `package.json` `main`, `bin` and `exports`. Source roots for the module map and traceability come from the shipped stack packs, and the compliance check's test globs are passed in by paqad's own callers. No pattern comes from network input, and `.gitignore` and other ignore files are matched by paqad's own ignore rules, not expanded by fast-glob. The advisory needs an attacker-controlled pattern, so the dismissal holds only while that stays true.

## 1.103.1

### Patch Changes

- 0c74902: The release job now tags and publishes GitHub Releases with the release token, so it can tag older versions whose workflow files differ from main.

## 1.103.0

### Minor Changes

- 65f3662: The HUD now has its own design in the Claude Code Desktop app. The band is a card with who is working and what it costs, one line that says what is happening, and a strip of the stages, the High Table and the delivery steps that apply to the change. A live state breathes and shows a running clock. The close button asks inline. The paqad Ledger on Desktop has equal tabs for Trust, High Table, Delivery, Record and Cost, and `Answer in chat` puts the open questions in the prompt box. The HUD now draws even when another plugin owns `/paqad`: its command is then `/paqad-hud`, and every hint names it. If paqad cannot read the session's record, the band says so. `/paqad hide` hides the band and `/paqad delivery` is an alias of `/paqad ships`. On a feature change, each prompt reminds Claude of the lane's stage list, and a task list that leaves the stages out is turned back once per turn. The idle terminal band now reads `Getting ready`.

## 1.102.1

### Patch Changes

- d523e07: The release now ships the Claude Code plugin, the `v<version>` git tag and the GitHub Release on every npm publish, decided from npm and the plugin repo instead of the changesets console output, and a check fails when the plugin falls behind npm. `paqad-ai decision resolve` also resolves packets the hooks write, which used to crash it.

## 1.102.0

### Minor Changes

- 631a12f: The Claude Code HUD now shows only the change this session is working on, and says plainly what it does not know.

  The band shows a change only when this session is on its branch, on the feature-development route, and has written a stage row for it since the route started. Otherwise it shows `no change in progress`. A verdict shows only when it was written for this change after its latest edit, gates read `not judged yet` until the stage that owns them has ended, and decisions show only for this change. Merge lights only when this change's own pull request is merged, commits count only this change's own, and cost counts only this change's feature-development turns or says `whole session`.

  The band is redrawn as one card with three instruments (STAGE, HIGH TABLE and SHIP), can be minimised, closed for the session or hidden for this project, and comes back with `/paqad show`. Other workflows get one status line with their own tokens. The side pane is now the paqad Ledger and opens on Trust. At session start, paqad quietly closes a change as `abandoned` when its branch is gone or merged and it has had no activity for 24 hours.

- 631a12f: Stage helpers on Claude Code now start with a short stage brief instead of re-reading the framework files.

  A new SubagentStart hook hands each paqad stage helper its role, its read list and instructions, the change, the lane, the previous pillar files and the exact stage commands, then records its entry check. If the hook is missing or fails, the helper loads the framework the way it did before. Codex is unchanged.

  Each stage helper can now run at its own effort and model. Planning, specification and review now default to high effort, checks and documentation sync to low, and development keeps the main session's effort. Every model defaults to inherit. Set any of them in `.paqad/configs/.config.models`: `stage_effort_<stage>` and `stage_model_<stage>`. The helper files are shared by every project, so they always keep these defaults, and a project value reaches a helper through `paqad-ai stage settings`, which prints JSON giving each stage its `effort`, its `model` and a `pass` string that says what the main session passes on that stage call. To run a stage at the main session's effort again, set its key to `inherit`; because its helper file still carries the default, the `pass` string then tells the main session to pass its own current effort level on that call. Each stage helper's record now notes the `requested_effort` and `requested_model`, which are what the project asked for, not a reading of what the helper ran at.

## 1.101.1

### Patch Changes

- 2b39aac: The release no longer stops on its own changeset check. Right after the version bump on main there is nothing left to release, so the check now steps aside when the branch has no new commits, and the npm publish and the plugin push can run.

## 1.101.0

### Minor Changes

- 39c5985: Tech debt, organization rollout, and the rest of the paqad HUD (closes #645, #620 and #639).

  **Problems a change finds but does not fix now have a home (#645).** `paqad-ai debt add` records each one as a `TD-<ULID>` file under `docs/instructions/tech-debt/`, ties it to the change that found it, and lists the open ones on the overview page. Review findings that are out of scope go there instead of being fixed on the spot or forgotten. The receipt, the HUD and the PR body show what the change raised, and `debt list`, `debt promote` and `debt close` keep the list honest.

  **One file puts paqad on every machine in your organization (#620).** `paqad-ai managed-settings --write <dir>` writes a Claude Code managed settings file that runs paqad's edit gates through `paqad-ai hook --managed` before every edit. Developers cannot turn it off locally, a repository without `.paqad/` is left alone, and a missing or slow paqad-ai blocks the edit and says how to fix it. The README has a new "Deploy for your organization" section with the folders, the checks and the rollback.

  **The plugin has one home.** `Eliyce/paqad-claude-plugin` is now the only plugin and marketplace. Each release builds the plugin here and pushes it there, with its own marketplace file, only after npm publish succeeds. The repository secret `PAQAD_PLUGIN_PUSH_TOKEN` must be able to push to `Eliyce/paqad-claude-plugin` before the first release after this one: a missing token or a failed push now fails the release job instead of skipping quietly. If you added the old `eliyce` marketplace by hand, add `Eliyce/paqad-claude-plugin` instead.

  **The HUD answers more questions (#639).**

  - A rule stop can be answered once in the HUD: "Let Claude fix it" by default, or "Allow once, recorded", which `paqad-ai rules override` writes to the change's evidence and the receipt shows. A stop your organization enforces is never offered.
  - A fix that changes behaviour now needs proof: `paqad-ai fix prove red` before the fix and `fix prove green` after it. Red then green passes; anything less reads Inconclusive with the missing step.
  - `delivery.json` says what really ships: the commit the change started from, its own commits, the commits riding along from other tickets, and the push, PR and CI. paqad warns when a branch carries other tickets' work, and `paqad-ai delivery-link commit-decision` records how the commit question was answered.
  - The paqad pane gains Trust, Ships and Record tabs, `/paqad receipt` draws a sealed card, decision questions show their evidence, paqad's own commands read as short chips, the spinner names the running stage, the footer names the lane, and the chat skips per-stage lines the HUD already shows.
  - `hud_chime=true` plays one short chime when a verdict lands. It is off by default.

## 1.100.1

### Patch Changes

- abf034e: Safer plugin move, honest gates and a cleaner codebase.

  - **Plugin move.** The move checks managed policy first, spots a claude.ai copy, finds the Desktop app's own `claude` (Windows too) and installs from the published plugin repo. Only one plugin copy runs per session, and plugin onboarding writes no hook chain.
  - **Session-safe stage rows.** Stage-agent rows carry the session that dispatched them and the subagent's own tokens. Decisions are judged by when they were opened, and the rules-loaded check is skipped on CI.
  - **Honest checks.** A test step with no readable results reads inconclusive, not passed. A project with no `package.json` still gets the usual Node commands, mapped from the lockfile and the scripts that exist.
  - **Safe config writes.** An older paqad never rewrites tracked config from a newer checkout, `project-profile.yaml` is edited in place, and `update` refreshes the managed `.paqad/.gitignore`. Doctor and rollback say what is installed and what happened.
  - **Pentest finding ids.** Finding ids are now built with sha256, so every id changes once with this release, and a retest still pairs the old findings with the new ones.
  - **No comments and no issue numbers.** The code no longer carries comments or issue numbers, and two strict rule scripts keep it that way in this repo. Onboarded projects are not affected.

## 1.100.0

### Minor Changes

- a5cbcd0: Honest gate evidence, a real acceptance-criteria-to-test check, mutation testing you can switch on, the High Table recorded and shown in the HUD, the cost of a change, and Claude Code Desktop task list and status hints. Closes #624 and #293.

  - **Not required and did not run are no longer passes.** A gate that had nothing to check now says "not required", and a gate that owed a check that did not happen says "did not run", with the reason. Neither counts toward "checks held", the PR comment, the report, the receipt or the HUD, and neither is cited as compliance evidence. The quality ratchet names the measures it actually took.
  - **Mutation testing is opt-in (#293).** Set `mutation_mode` to `warn` or `strict` (off by default; the team value is a floor) and call paqad's backstop from your own CI or pre-push hook. Your test command runs first, then the mutation tool you install for your stack. Under `strict` a surviving mutant fails that step. It never runs at the end of an agent turn, and the docs say what each host tier does.
  - **A real acceptance-criteria-to-test check.** Each change gets its own map from the frozen spec's automated criteria to the tests changed on the branch. A criterion is proven only by a changed test that names it in a test title, a describe title or an `@obligation` tag. With no frozen spec the check reads not required; an unproven criterion fails and is named.
  - **The High Table, recorded as it happens.** Each expert and the chief architect can run as its own subagent (new `paqad-expert` and `paqad-chief-architect` agents). A new `high-table.jsonl` in the change's bundle records when each seat was seated, started and finished, its budget and its exact tokens. Notes from seats that finish together are merged one role at a time, so none is lost. A table that meets after the spec is frozen is flagged and credited with no spec line.
  - **The High Table in the HUD.** On the graduated and full lanes the band shows a High Table row with one dot per seat plus the chief. A live card in the chat follows the seats as they work, and a new paqad pane has a High Table tab (the round table, each seat's detail and track record, the chief's rulings and who shaped each spec line).
  - **The cost of a change.** paqad adds up the tokens from the session's transcript and each paqad subagent's own transcript, for the change only, and writes `cost.json` to the bundle. Money comes from a dated price table that ships with paqad and is always labelled an estimate. The band's cost pill, `/paqad cost`, `paqad-ai status --hud` and the pane's Cost tab show the total and the split by stage, by expert and by the chief. Nothing calls a model or the network.
  - **Claude Code Desktop task list and status hints (#624).** The router now tells the agent to show paqad's progress through the host's own task list, status line and needs-you flag, and to give each decision option a short preview.

## 1.99.3

### Patch Changes

- 94fcde8: Updated the runtime dependencies to their current releases: execa 10, openai 7.34, @inquirer/prompts 8.7.3, chalk 6.0.1 and handlebars 4.7.10. Nothing changes in how you use paqad. Installing still works on Node 22 or later.
- 94fcde8: Fixed the status line showing "Safe to merge" after a turn whose end-of-turn check was skipped. A skipped check now leaves the last real verdict on screen. A turn in which only the stage agents edited files is now checked as the orchestrator session's own work, and a prompt that names a stage, such as "run documentation_sync", keeps an open change on feature development instead of turning it into a docs, question or no-workflow turn. A specialist request such as a security review still goes to its own workflow.

  The bundle receipt.json is now sealed after every check has run, so its result matches the verdict on the status line. A quality measure that could not be taken, for example because there is no coverage report, is still listed on the receipt but no longer makes it read Inconclusive.

- 94fcde8: The move to the Claude Code plugin no longer gives up too early on the Desktop app. Sessions only count toward undoing the move once Claude Code has actually installed the plugin, since the Desktop app can take a few starts to do that. If the plugin is still not installed a week after the move, paqad undoes it and tries again later. While it waits, `paqad-ai doctor` says `npm (migration installed: waiting for Claude Code to install the plugin)`.
- 94fcde8: Fixed `paqad-ai checks run` reporting into the wrong change and printing "0 tests" for a passing run. It now uses `SE_SESSION` before `CLAUDE_SESSION_ID`, the same order as every other paqad command, so a stage agent's report lands in the orchestrator's change. The test count reads vitest's nested TAP output, a passing run with no countable tests says "count unavailable", and new pnpm projects get `pnpm test --reporter=tap` without the `--` that made vitest ignore the reporter.
- 94fcde8: Fixed a disabled project writing a "completion deferred" row when a turn ended while a paqad stage agent was still running in the background. A disabled project now writes only its one disabled-session audit row, as it does on every other turn.
- 94fcde8: `paqad-ai doctor` now names the settings file that keeps the npm hooks running after the move to the plugin. It used to blame the project settings even when the hooks were wired in your user settings. It now checks your user `~/.claude/settings.json` first (or the one in `CLAUDE_CONFIG_DIR` when you set it), then the project files, and names each file it finds.

## 1.99.2

### Patch Changes

- c84bf5a: Fixed a Claude Code session running both the plugin and the npm hooks when the plugin stays passive in an npm-onboarded project. Now exactly one copy runs, so the Stop check no longer writes duplicate rows and prompt notes no longer print twice. `paqad-ai doctor` also says when a project still runs the npm hooks after the move to the plugin.

## 1.99.1

### Patch Changes

- 57d35b8: paqad no longer writes other tools' MCP config files (#622). Older versions wrote paqad's own MCP suggestions to `.cursor/mcp.json`, `.vscode/mcp.json`, `.junie/mcp/mcp.json`, `.codex/mcp.json`, `.windsurf/mcp.json`, `.continue/mcp.json`, `.gemini/mcp.json`, `.antigravity/mcp.json` and `.claude/settings.mcp.json` on every onboard and update. Those files belong to the tools that read them, so any MCP server you had set up in one of them was replaced and lost. We are sorry about that.

  Now the suggestions live in paqad's own `.paqad/mcp-recommendations.json`, as a plain list of server names, what each one provides and why it fits your stack. paqad never configures a server for you. On the next onboard or update, paqad removes only the files it wrote itself: a file is deleted only when it carries paqad's `resolved_artifacts` marker, holds nothing at the top level besides that marker and `mcpServers`, and none of its servers has a `command`, `url`, `type`, `serverUrl`, `args`, `env`, `headers` or `transport`. Every other file is left exactly as it is. When a file carries paqad's marker but is kept anyway, `.paqad/logs/mcp-cleanup.log` says why; your own files without the marker are not logged. `paqad-ai join` only removes git-ignored copies, so it still changes no tracked file.

  If you lost an MCP server to an older version and the file is tracked in git, you can find your old setup with `git log -p .cursor/mcp.json` (use the path of the file you lost) and copy the server back.

  `paqad-ai doctor` now reports MCP as `MCP servers (recommended)` with an `info` status. It lists the servers suggested for your stack and the ones already in your root `.mcp.json`, and it never passes or warns. An `info` check does not change the overall doctor result. The dashboard says "MCP server(s) recommended" instead of "Configured".

  `paqad-ai new project` now ends with its own panel (#612). It says the workspace was created, that the application stack is still undecided, and gives one next step: choose your application stack, by running discovery or `paqad-ai onboard` once the stack exists. It no longer shows the onboarding steps such as "create documentation", which only make sense once a stack exists. `paqad-ai onboard` shows the same panel as before.

  Site map evidence on Laravel now points at real files (#500). A route found by `php artisan route:list` cites the route file line that declares it and the controller method that handles it, a console command cites the class that declares it, and a scheduled task cites the line that schedules it. The artisan command now lives only in the evidence note, so a map that cites `routes/web.php` no longer reads as missing a route that artisan found. A route that a package registers cites its file under `vendor/` when your dependencies are installed; otherwise it lands in the blocked check. A route or schedule that cannot be traced to a file, such as a closure, is shown as a blocked check that lists it, instead of being added with no file. A command scheduled by its class, like `Schedule::command(SendReports::class)`, is found through that class. Artisan built-ins with no source in your project are skipped. Artisan also runs the way your project runs it, read from the migrate command in `.paqad/project-profile.yaml`: Sail (a bare `sail` means `vendor/bin/sail`), docker compose `exec` or `run` (run with no terminal), or host PHP. Leading settings like `APP_ENV=testing` are dropped. If that command still holds a placeholder like `<php-service>`, or chains commands with `&&`, `||`, `;` or `|` before artisan, the map tells you what to fix. Because the evidence changed, an existing Laravel map reads as drifted once after this update; run the map again to refresh it.

## 1.99.0

### Minor Changes

- 00646d6: The paqad plugin for Claude Code now shows where your change stands, in a band above the prompt (#639). One line says what just happened and what comes next. Under it, the Stage row shows the eight stages from Intake to Deliver with a live clock on the one that is running, and the Ship row shows Edit, Commit, Push, PR, CI and Merge. Merge always stays yours. The band says one of nine states in words: Ready, Working, Branch warning, Needs you, Stopped, Inconclusive, Safe to merge, Needs your attention or Paused. Any open flag turns it amber, even at Safe to merge, and a pill counts the flags. Anything paqad has no record of yet reads "not yet", including the cost pill.

  Type `/paqad` for the same picture as text, or `/paqad status`, `/paqad decisions`, `/paqad rules`, `/paqad receipt` or `/paqad cost`. They answer from paqad's own records and cost no model turn.

  The band only shows. Every check is still one of paqad's hooks, and they block exactly as before whether the band is on, off or broken. It reads only `.paqad/`, never calls a model or the network, and starts no process.

  It is on by default. To turn it off, set the plugin's `view` option to false in `/config`. It also stays away when the project was never onboarded, when paqad is turned off, in a cloud session, and on Claude Code older than 2.1.301.

  The change's bundle now keeps each rule finding in `rule-run.jsonl` and each near-copy in `duplication.jsonl`, and the band counts the open ones in its flag pill.

- 00646d6: The spec pipeline, its expert panel and strict adoption are now on by default (#640). On the next update, a project that never set these keys gets all three on the graduated and full lanes: the specification stage runs `paqad-ai spec pipeline`, the four standing experts (product owner, application architect, user-flow writer, QA engineer) sit at every spec, and a hand-written spec freezes only with `--manual --reason "<why>"`, which is recorded. The fast lane is unchanged: no pipeline run, no experts and no extra bundle files.

  A change that is already open when you update keeps going as it was. If its spec was frozen before the update, it is not asked for the pipeline's files (`request.md`, `clarification.json`, `experts.json`) or for a pipeline record on the spec, and the completion check says so: "Spec frozen before the spec pipeline was on, so not required". If its spec is not frozen yet, it goes through the pipeline like any new change.

  A project that already set any of these keys keeps its value. `paqad-ai update` never writes the new defaults into a config file.

  Cost: the standing experts carry about 24k tokens of budget per spec, under a 40k ceiling by default. `paqad-ai doctor` now shows each setting and where its value came from.

  To switch any of them off, add a line to `.paqad/configs/.config.*` (for the whole team) or `.paqad/.config` (just for you), or set the matching `PAQAD_*` environment variable:

  - `spec_pipeline_enabled=false` turns the whole pipeline off (`PAQAD_SPEC_PIPELINE_ENABLED=false`)
  - `spec_pipeline_experts_enabled=false` keeps the pipeline but drops the experts (`PAQAD_SPEC_PIPELINE_EXPERTS_ENABLED=false`)
  - `spec_pipeline_adoption=warn` lets a hand-written spec freeze again (`PAQAD_SPEC_PIPELINE_ADOPTION=warn`)

### Patch Changes

- 00646d6: Routing gets your intent right more often, and a wrong label is easy to fix.

  - `paqad-ai route set` now refuses to leave feature development only when your own session edited source this turn. Another session working in the same folder no longer blocks your correction. If no session id can be found, the correction is allowed and written to the route override log.
  - Setting the route back to a paused workflow resumes that paused change, so no stray paused copy is left behind.
  - Messages about the work itself, such as posting an issue, updating a draft or linking a ticket, go to project question instead of feature development. A real code request that mentions a report, a plan or a doc still goes to feature development.
  - A subagent's report or a background task notice is never routed as if you had typed it, wherever its notice banner sits in the message.

- 00646d6: Atomic file writes no longer fail now and then on Windows (#647). When another writer holds the target for a moment, Windows refuses the final rename with `EPERM`, `EACCES` or `EBUSY`. paqad now retries that rename up to five times (waits of 10, 20, 40 and 80 ms) and removes its temp file if it still gives up. macOS and Linux behave as before.
- 00646d6: The last users of the retired changed-files cache now read git instead (#651).

  - The generated `scripts/refresh-registry-diff.sh` takes its changed files from `git status` plus everything committed on the branch since it left the default branch (what `origin/HEAD` names, else `main`, else `master`). Before, it looked for a cache file nothing writes, so it always ran the full refresh. It still runs the full refresh outside git or when git reports no changes.
  - The `diff-doc-sync` skill reads the changed files from `paqad-ai review digest` (or git) instead of the cache.
  - The unused `track-file-changes.sh` hook script, which no hook config ever ran, is gone.

## 1.98.2

### Patch Changes

- 9518154: Fixed the move from the npm package to the Claude Code plugin (#648). It is still off by default.

  - It now uses the right marketplace, `Eliyce/paqad-ai`. The old name did not exist, so the move could never work.
  - When `claude` is on your path, paqad registers the marketplace, installs the plugin, and checks that Claude Code really recorded it. If any step fails, it falls back to your user settings and writes the reason to `~/.paqad-ai/logs/plugin-migration.log`.
  - paqad now counts real Claude Code sessions before it undoes a move. Three sessions in a row with no sign of the plugin undo it. Before, it counted background updates, which only run when a new version is out, so a broken move could sit there for weeks.
  - An automatic undo is tried again after a day, up to five attempts, so a blocked download recovers once access is back. A `paqad-ai plugin rollback` you run yourself stays final.
  - If you turn the plugin off in your Claude settings after the move, paqad records that you declined it, shows it in `paqad-ai doctor`, and never turns it back on.
  - `paqad-ai plugin rollback` now really removes the plugin through `claude plugin uninstall`, as its message says.
  - Choosing `claude_install_mode=plugin` right after a skip no longer waits a day. Skips caused by your own config or environment never hold back the next run.

## 1.98.1

### Patch Changes

- 9f74a03: Changed files now come from git only (#646), and a test cleanup flake is gone (#649).

  - paqad no longer reads `.paqad/session/changed-files.json`. Nothing writes that file any more, and a leftover copy with one still-dirty entry used to hide every other file you edited, so `paqad-ai review digest` and the completion checks could describe a single file out of a dozen. The changed files are now what git reports: your working-tree changes plus everything committed on the branch since it left `main` or `master`. A leftover cache file is simply ignored.
  - When git cannot tell where the branch started (no `main` or `master` branch, or no commits yet), paqad uses the working-tree changes alone. Outside a git repository there are no changed files.
  - Module-health session evidence, the differential refresh in `paqad-ai refresh`, and traceability read the same git list. A clean tree with no commits on the branch now means no changed files for them, where a missing cache file used to.
  - Tests that run the prompt gate now remove their temporary project with retries, so the background context refresh still writing into it can no longer fail the cleanup with `ENOTEMPTY`.

## 1.98.0

### Minor Changes

- 0d78006: The paqad HUD's groundwork: one honest record before anything is drawn (#639, Wave 1).

  - **Rules match the change's own files.** paqad's own `.paqad/` files (decision packets, session markers) no longer pull a rule in, and files the session inherited dirty and never touched no longer count. `rules load` and the end-of-change check use the same list.
  - **One decision packet shape.** A decision opened with `paqad-ai decision create` now shows in Approvals, is counted by the end-of-change check, and can be reused by the spec pipeline once answered. Older packets are read as before. One broken packet file no longer blocks new decisions.
  - **One verdict word everywhere.** The chat receipt, `report.html` and the `paqad-ai evidence` PR comment now say the same word for the same run. An inconclusive check used to read Safe to merge in the report and Needs your attention in the PR comment; it now reads Inconclusive in all three. CI blocking is unchanged.
  - **One narration format.** Every paqad line, including the route line, now starts with `**▸ paqad** ·`.
  - **paqad keeps its own receipt every turn**, in `.paqad/session/hud/`, without printing anything new.
  - **The HUD snapshot.** `paqad-ai status --hud` (or `--hud --format json`) shows where the change stands: route and lane with the reason, stages, the High Table as recorded, gates by strength, flags, decisions, what ships and the verdict. It is built only from paqad's own records, refreshed by the paqad commands and hooks, and never changes what a hook decides.

### Patch Changes

- 0d78006: One reader for `.paqad/session/changed-files.json` (#544).

  - `paqad-ai review digest` could be headed by files from an earlier, already-merged change, because it trusted the session cache as-is. It now reads changed files through the same git reconcile the completion checks use: cached files that are clean and already in base history are dropped, and with nothing left it lists the branch's real working-tree changes.
  - Module-health session evidence and the differential refresh in `paqad-ai refresh` no longer act on those stale entries either. With no cache they behave exactly as before.
  - Traceability read the cache as a `{ files }` object that nothing writes, so it never saw a single changed file. It now reads the bare array like every other reader.
  - The file has exactly one reader in the codebase now, so a shape change can never again break one consumer silently.

## 1.97.0

### Minor Changes

- f235574: Add the automatic npm → paqad-plugin migration for Claude Code users (#621), **off by default**.

  - New layered config knobs `plugin_migration` (`on`|`off`, default `off`) and `claude_install_mode` (`auto`|`plugin`|`settings`, default `auto`).
  - `maybeMigrateToPlugin()` runs best-effort at the end of `paqad-ai update --silent`: it evaluates the skip conditions (migration off, install mode `settings`, no `claude-code` provider, CI/headless, already present, managed policy, retry rules), takes a single-flight machine lock, and installs via the `claude` CLI (Path A) or a safe additive merge into the user's `~/.claude/settings.json` (Path B). It never throws, never blocks, never prints in a session, and never touches a tracked project file or the npm package.
  - Confirms the plugin actually loaded (via `plugin-seen.json`) before the npm copy steps aside, and undoes the move after 3 npm sessions with no sign of it (`rolled-back`). Supports the claude.ai synced route.
  - `paqad-ai plugin rollback` undoes the move, pins `claude_install_mode=settings`, and prints the documented message; `paqad-ai doctor` reports the Claude Code install line.
  - Guardrail: a new `tests/e2e/stage-enforcement-contract.e2e.test.ts` fences every paqad stage hook's block/allow behavior on both the npm and plugin routes.

  The fleet-wide default flip (`plugin_migration` → `on`) and the manual sign-off scenarios are intentionally out of scope and ship separately.

### Patch Changes

- f235574: Fix #641: onboarding through the Claude Code plugin no longer takes over the shared npm framework link, and npm-onboarded repos run a single hook chain.

  - `bootstrap.ts` now applies the same plugin-aware rule as the plugin's SessionStart when `onboard`/`join`/`install` run from the plugin bin: a link pointing at a working npm install is left untouched, and a missing or dangling link is pointed at `${CLAUDE_PLUGIN_DATA}/runtime` rather than the version-specific cache runtime. Running from the npm install is unchanged.
  - The plugin's one-copy handshake (`hasLiveNpmHookLines`) now also inspects the project's `.claude/settings.json` and `.claude/settings.local.json`, so the plugin stays passive in a repo the npm copy already wires — each paqad hook fires once per event, not twice.
  - Onboarding under the plugin omits the npm hook chain from the project's `.claude/settings.json`, since the plugin supplies its own.
  - `onboard --stack <bad>` now lists the valid stacks instead of an opaque schema error, and the `onboard` skill documents the `--detect --json` null-stack case.

## 1.96.1

### Patch Changes

- 7d420a9: Fix three Claude Code plugin bugs from 1.96.0 (#636).

  - The plugin installs at user scope and ran its hooks in every repo, so in a project that was never onboarded the entry gate blocked the first edit and the model was pushed to create a `.paqad/` folder in an unrelated repo. Every plugin-reached hook now stands down to a pure no-op (exit 0, no output, no `.paqad/` write) when the project has no `.paqad/framework-path.txt`; enforcement in onboarded repos is unchanged.
  - `plugin-session-start.mjs` used a raw entry-point guard (comparing the module URL against an un-normalized `process.argv[1]`) that missed on Windows, on paths with spaces, and on symlinked paths (macOS `/tmp` to `/private/tmp`), so the hook silently did nothing — no PATH setup, no version refresh. It now uses the same realpath-safe guard as the other hooks, shared in one place so the broken form cannot return.
  - The plugin re-pointed the shared `~/.paqad-ai/current` link at its version-specific cache runtime; when that cache was removed, the link dangled and blocked every edit in every npm-onboarded project (and in Codex/Gemini). The plugin now never takes over a link that resolves to a working npm install, and when it fills a missing or dangling link it targets a stable location that survives cache version churn. `paqad-ai doctor` now prints the exact repair command for a dangling link.

## 1.96.0

### Minor Changes

- 1147d3e: Ship paqad as a Claude Code plugin that works on its own, without the npm package (#616).

  Inside Claude Code, install with `/plugin marketplace add Eliyce/paqad-ai` then `/plugin install paqad@eliyce`, and drive it with the `/paqad:onboard`, `/paqad:join`, and `/paqad:dashboard` skills. The plugin ships a self-contained `dist/` (no `node_modules`), resolves the optional RAG engine on demand and installs it in the background, keeps a single copy active per session alongside an npm install, puts `paqad-ai` on the session PATH, and keeps itself current. Every other host keeps using the npm package exactly as before; nothing changes for existing npm-only users until they install the plugin. Automatic migration and fail-closed plugin gates are out of scope here.

## 1.95.1

### Patch Changes

- 5123d90: Realign the Claude Code hook layer with Claude Code 2.1.228-2.1.302 (#615): resolve the project root from the hook payload's worktree `cwd`, recognise Desktop `[SYSTEM NOTIFICATION - NOT USER INPUT]` banners before routing and ticket intake, keep the prompt hook's output under the host's 10,000-character cap, defer the completion verdict while a `paqad-<stage>` subagent is still running in the background, route slash commands by name instead of as prose, and make the three edit gates fail closed with `onFailure: "block"` and a 10-second timeout. Codex, Gemini and advisory hosts keep their current behavior.

## 1.95.0

### Minor Changes

- fe689c4: Add `paqad-ai new project <name>` and the Slice 3 setup journey (#596). `new project` creates a development workspace — directory, git, `.paqad`, docs scaffolding and host entry files — with an explicitly undecided application stack (no framework default) and a safe non-empty/rerun guard, reusing the onboarding engine without touching `onboard`/`install`/`update`. A new `paqad-ai setup` command records and validates a dependency-ordered setup plan, tracks step state, and verifies readiness to develop; paqad records the official install steps but runs no installer itself. `paqad-ai setup onboard` then onboards the actual installed stack of a created workspace — detecting the stack, turning the undecided placeholder commands into real ones and refreshing generated surfaces while preserving team-owned settings; it refuses to onboard a still-empty workspace rather than defaulting to a framework (SET-03/SET-05).

## 1.94.1

### Patch Changes

- c8b26ea: A closed change no longer comes back as the session's active change (#591). After a change passed verification and was closed, the per-session control could still name the closed bundle as `active` — a closed bundle still carries stage rows, so `reconcileSessionControl` returned it as active and the next `stage start` (or live edit) appended into the finished bundle instead of opening a new change.

  `reconcileSessionControl` now releases a stale `active` pointer at a currently-closed bundle (its last lifecycle row is a `close`) and falls through to branch-scoped adoption or a fresh mint, so the next stage opens a new change. A dangling pointer at an unmaterialized dir is still left in place (REPOINT-ONLY), and the broad "ever closed" filters (`listAdoptableFeatures`, `sessionClosedAnyFeature`) are unchanged. Reopening a closed change on purpose with `paqad-ai resume --feature <ref>` keeps working: it appends an `open` row (append-only — the `close` row stays) and flips the bundle's status back to `active`, so the next stage row lands there.

  Every write of the session control now stamps `written_by` (the writing verb or hook) and the writer's `pid`, so the next stale rewrite is traceable to its source. The fields are additive — a control written before them still reads.

## 1.94.0

### Minor Changes

- 301f9b7: Standalone Discovery workflow for existing onboarded projects (#597). Discovery helps you shape an uncertain idea or a no-code improvement brief into a practical next step, through six enforced, resumable stages: understand, investigate, refine, decide, check readiness, and hand off. It is its own workflow — its own routing outcome, its own stages, its own script-written evidence, and its own isolation boundary — reusing the existing evidence envelope, session-ledger substrate, and decision writer rather than a parallel copy of them.

  A Discovery run keeps everything it produces under `.paqad/ledger/delivery/<slug>-<ULID>/` (already covered by the managed `ledger/` gitignore, so nothing is committed): the run identity and lifecycle, the correctable brief, attributable research sources, expert contributions and the chief synthesis, the settled decisions, the readiness verdict, the durable hand-off, the stage-evidence ledger, stage-local context receipts, and a read-only `report.html` you can hand to a fresh person. Every artifact is minted and hashed by a script — a hand-edited or model-authored file never clears a Discovery gate — and each stage's end must point at a real artifact to count as done.

  Discovery is isolated from feature-development and from other sessions: it never extends the feature-development stage order, never writes into a feature bundle, and never blocks an unrelated workflow, session, or project. Ownership of a run is proven only by the session's own state plus the run's own owner stamp, never a shared pointer or the latest directory. Drive a run with the new `paqad-ai discovery` command group (`start`, `stage`, `brief`/`source`/`contribution`/`synthesis`/`decisions`/`readiness`/`handoff`/`context` record, `status`, `resume`, `set-status`, `report`). The capability arrives through the normal package update — no re-onboarding and no edits to existing project files; a run's evidence is written only when you actually run Discovery.

### Patch Changes

- 7e33f83: Prompt router no longer mislabels questions as feature-development, and a clean working tree no longer triggers a whole-tree rule block (#580).

  The deterministic classifier used to match code-change keywords (`fix`, `bug`, `add`, `build`, `cleanup`) as plain substrings and rank them above the question check, so "What does the **add**ress field store?", "Can you explain the de**bug** output?", and "Why does the pre**fix** get dropped?" were all routed to feature-development — loading rules, code-scope retrieval, and completion enforcement for a plain question. Keywords now match on whole words with explicit inflections (so "added" still matches but "address" does not), the project-question check runs before the code-change keywords, and an explicit "no code" or "file an issue" ask routes to project-question. Genuine code requests, including polite ones like "Can you add a logout button?", stay feature-development.

  At the completion seam an empty change set now means nothing to enforce: a turn with a clean working tree returns a `⚪ scripted rules: skipped (no files changed this turn)` verdict instead of scanning the whole repository and blocking on pre-existing violations the turn never touched. Explicit whole-tree scans keep their behaviour.

  New `paqad-ai route set <workflow>` command lets the agent correct the hook's label when its deterministic guess disagrees with the intent the agent read: it rewrites the active per-session route, clears any stashed lane on a non-feature correction, and records an `agent-override` audit row. It refuses to leave feature-development once source files have been edited this turn.

- da20c3b: Fast-lane edits are now recorded as development, checks and documentation_sync stages (#590). The pre-mutation edit gate has been lane-aware since #324 — a fast-lane change needs only `planning`, not a frozen spec — but the live stage writer (and the on-entry narration) still demanded both `planning` and `specification` on every lane before it would record an edit. The two disagreed, so a fast-lane change left no `development`, `checks` or `documentation_sync` rows in `stage-evidence.jsonl` even though real source, test and doc edits happened, and the change could read as incomplete or pass with stages that were never recorded live.

  The lane-to-required-pre-code-stages decision now lives in one shared helper, `requiredPreCodeStages(lane)`, that both the gate and the writer consult, so they can never drift again. The effective-lane resolver (the `sensitivity: high` → `full` floor, with a null lane failing safe to `full`) has been lifted into a shared `effective-lane` module both sides import, so a fast-lane edit to a high-sensitivity path is held to `full` by the writer exactly as the gate blocks it.

- 9dac1c3: Fix lane governance so the stage-isolation safeguard can no longer silently disable itself and report a clean bill of health (#602).

  The lane that governs the end-of-change isolation check was a first-glance guess the operator could not correct, was last-writer-wins (a small follow-up could relabel a large build "fast"), and the check only fired on a graduated/full label — so a wrong or missing label switched the check off with no signal. Now:

  - **Operator override** — `paqad-ai lane set <fast|graduated|full>` records the real lane for the active change; that recorded `feature.json` lane is what the isolation check reads.
  - **Monotonic lane** — the recorded lane only ever rises. A later small-fix turn can never downgrade a large build, and `lane set` refuses a downgrade rather than lowering it.
  - **Unresolved is loud, not silent** — a feature-development change on a subagent-capable host whose lane never resolved, with no isolation evidence, now reads Inconclusive with a "not classified — isolation not verified" note instead of a clean green (never a hard block).
  - **Bare ticket/URL** — a prompt that is essentially just a ticket reference or a link no longer sets the safety lane from its surface text; the lane is left unresolved-pending-read.
  - **Honest wording** — the contract and the onboarded-project overview now describe isolation as expected-and-detected at end-of-change, not hard-enforced before the edit.

## 1.93.0

### Minor Changes

- c70761b: Seat four standing experts at every spec run and make every expert speak the project's own words.

  The spec pipeline now seats a product owner, an application architect, a user-flow writer and a QA engineer on every run, alongside the specialists the detector picks. The new application-architect role says where a change lands in this app and what it is built from. Every expert brief carries a Project voice section built from the stack pack and the module docs, a deterministic voice check flags a target the project does not name, and the chief settles the word before the spec is written. The frozen spec keeps a snapshot of who contributed each line. Everything is off until the pipeline and the experts are turned on.

## 1.92.0

### Minor Changes

- af3db24: One evidence packet per change (#581). Everything a change produces now lives in its feature bundle, and nothing goes to `.paqad/_specs/` any more. The signed `spec.md` is kept in the bundle, the pipeline's request, clarification and expert records are folded in, each fact is stored once, and every file and row carries the same six-field header. `evidence.jsonl` is always written, and the receipt seals its hash instead of copying rows. Existing projects migrate once, automatically, or by running `paqad-ai evidence migrate [--dry-run]`.

  The `.paqad/` schema version goes up to 1.1.0 for this. The first `paqad-ai update` or onboarding after you upgrade moves your old spec runs into their bundles on its own, one time. Files it cannot place are left in `.paqad/_specs/` and listed, a change another session still has open waits for a later run, and a file that cannot be deleted gives a warning instead of stopping the update. Pass `--session <id>` to `paqad-ai evidence migrate` so your own open change is not treated as someone else's.

### Patch Changes

- 07cbad5: The turn a change passes now writes its evidence before closing it (#581 follow-up). Before, the change was closed first, so `evidence.jsonl`, the receipt, the AI-BOM, change metrics and `decisions.json` were never written on that turn, and the completeness gate never ran. A change the completeness gate fails now stays open so the next turn checks it again. The isolated-stage count also includes stages recorded before an upgrade, and the test suite no longer writes into the developer's home folder.

## 1.91.1

### Patch Changes

- 29a82f1: Two paqad sessions in the same checkout no longer trip over each other. The end-of-turn check and its rule-scripts now run only in the session that made the change, so a question asked in a second window is never blocked by another window's work. Each session also gets its own entry sentinel and its own route pointer, and a prompt that is not feature development no longer receives the rule text meant for someone else's change.

## 1.91.0

### Minor Changes

- 5c7b0fb: Visual evidence now actually runs from the Stop hook, and a frontend change hears about it at every stage (#579).

  - **The gate fires again.** The Stop hook loads `dist/index.js`, one folder shallower than the CLI, and the package root was worked out with a fixed `../..`. From there it pointed one folder too high, no stack packs loaded, and every change read as "not frontend". paqad now walks up to its own `package.json`, so every bundle finds the same runtime folder. A new end-to-end test runs the built bundles and the real Stop-hook script to keep it that way.
  - **A broken install says so.** If your profile names frameworks but paqad loads none of its packs, the visual-evidence gate reports an install fault (fail under strict, inconclusive under warn) and `visual-evidence run` / `plan` exit 1, instead of quietly passing the change.
  - **New: `paqad-ai visual-evidence attach <png...> [--ac AC-3] [--label "..."]`.** When a scripted capture cannot run here, attach your own PNG screenshots. They are hashed and recorded as agent-attached (never shown as scripted captures), and a later `visual-evidence run` keeps them. `--ac` must name an acceptance criterion in the frozen spec, so a typo is refused instead of tying screenshots to nothing. A failed scripted step keeps the result partial whichever of `run` and `attach` came first, so attaching screenshots never hides a real gap.
  - **Strict mode is stricter.** Under `visual_evidence_mode=strict`, a frontend change with nothing captured because there is no documented flow or capture script now fails. Attach screenshots, or record a waiver decision resolved with `waive`: the planning readiness decision when one was opened, otherwise one you create with `paqad-ai decision create` (the failing gate prints the exact command). A waived change reads skipped, never pass. Warn mode is unchanged and now prints a "⚪ visual evidence: skipped (reason)" line.
  - **Asked for earlier.** `plan compile` opens one decision pause when the change is frontend and this machine cannot capture screenshots yet (plan steps can now list the `files` they touch). `spec freeze` asks for at least one `(proof: visual)` criterion on a frontend change. The first frontend edit carries a one-time reminder to the model.
  - **On the record.** The late gates (bundle-completeness, visual-evidence, rules-loaded) are now written to the bundle's `evidence.jsonl` when the evidence ledger is on, skips included, with a new `skipped` verdict that never counts as a pass or a fail. `audit export` grades a skipped row informational (OCSF severity 1, CEF 1), and the evidence packet shows it with a grey dot instead of the amber "needs a look". A passing gate now names the `(proof: visual)` criteria it covers.

## 1.90.1

### Patch Changes

- c72b67b: fix(#576): make `paqad-ai join` fully provision a teammate machine and stop the first prompt of a session from falsely blocking at Stop

  - Route every prompt (including the not-yet-loaded first prompt) so a read-only turn is classified non-feature and the Stop backstop no longer blames pre-existing dirty tracked files; also capture a session-start dirty-file baseline the completion backstop subtracts, and treat `.ai/` as host-agent config.
  - `join` now performs the global framework install (`~/.paqad-ai/current` + stage agents), regenerates the per-machine detection/stack-snapshot/stack-drift artifacts, builds the code-knowledge index (also on `onboard`), runs delivery detection, seeds the quality baseline from HEAD, and rebuilds the RAG index without rewriting tracked files.
  - The classifier routes interrogative project questions (how/where/what/why/explain/show me/example) to `project-question`.
  - Git-hook installation skips a git-tracked hooks dir and reports the snippet instead; `join` closes four small correctness gaps (dead sentinel write, framework-version epoch seed, stale host-config refresh, tracked-aware ignore check); and the load directive steers the agent to its file-read tool to avoid the zsh `=` trap.
  - `doctor`'s missing-artifact remediation now points at `paqad-ai join`.

## 1.90.0

### Minor Changes

- 6791fef: fix(#573): build the prompt-route seam so a change gets a real lane, and enforce stage isolation instead of trusting it

  Stage isolation (#567) never ran on Claude Code, and nothing detected that. The cause was
  a build defect, not model behaviour: `tsup.config.ts` never emitted
  `dist/pipeline/prompt-lane.js`, which the `UserPromptSubmit` hook imports inside a
  soft-fail. The import threw `ERR_MODULE_NOT_FOUND` on every prompt of every installed
  copy and exited 0, so the prompt router never ran, the recorded lane was always null, and
  the router's "graduated or full lane" precondition for isolation was never satisfied.
  `dist/planning/ticket-ref-detect.js` was missing the same way, so the ticket-intake hook
  was dead too. Unit tests import these modules through the source alias, so CI stayed
  green the whole time.

  Both entries are now built, and a parity test derives the expectation from the hook
  sources: every `../../dist/<path>.js` a runtime hook imports must be a declared tsup
  entry, so a newly added hook cannot ship a dangling import. Hooks no longer swallow a
  failed compiled-half load either; they append one line to `.paqad/logs/hook-failures.log`
  through a shared helper that never throws.

  `writeStageAgents()` now runs from the update path, not only from onboarding. An
  already-onboarded project upgrades through `paqad-ai update`, which previously rendered
  the new `SubagentStop` hook and none of the six agents it points at.

  With a real lane available, a skipped isolation is detectable and enforced. Every
  stage-evidence row records the `agent` that wrote it (`orchestrator`, or the dispatched
  `paqad-<stage>`), and on a graduated or full lane on a subagent-capable host a bundle
  with no `context-efficiency.jsonl` fails the completeness gate by name instead of
  reading "Safe to merge". This stays silent on the fast lane, on hosts without subagent
  dispatch, and whenever the lane is unresolved, so it cannot false-fail legitimate work.

  Two honesty fixes in the same gate, both found during the RCA: a stage whose recorded end
  precedes its own start is now an ordering violation rather than folding to `complete`,
  and a gate blocked by an ordering violation names the violated pair instead of printing
  the literal, unactionable `missing stage(s): []`.

## 1.89.0

### Minor Changes

- e6c3737: feat(#567): run each feature-development stage in a fresh subagent, with the evidence bundle as shared memory

  Stage isolation is core-engine behavior for Claude Code and Codex — there is no config knob.
  On the graduated and full lanes, each mandatory feature-development stage runs in its own host
  subagent seeded with the paqad contract, the previous pillar artifact, and its stage
  instructions; the main chat stays a lean orchestrator that routes, narrates, asks the
  decision-pause questions, and speaks the receipt. Nothing is compacted because nothing
  accumulates — later stages no longer re-carry earlier stages' history, so input tokens drop on
  every graduated and full-lane change. The fast lane and non-subagent hosts run the stages in a
  single context, unchanged.

  Install and update always render six stage agents per host at user scope (never into a project
  directory), a record-only `SubagentStop` hook appends a per-bundle `context-efficiency.jsonl`
  stream, and the in-flight fork guard refuses to mint a third bundle on one branch. Every stage
  records under the orchestrator's session id, so the bundle keeps one identity — and each stage
  subagent proves its own cold framework load through an `agent_id`-keyed entry sentinel (a
  subagent shares its parent's `session_id`, so the sentinel keys on the distinct `agent_id`).
  paqad's Node code still calls no LLM; the host's subagent runs the stage.

## 1.88.0

### Minor Changes

- 1952ac7: feat(codex-cli): wire paqad's full hook set so feature-development stages are enforced on Codex exactly as on Claude Code (#566)

  Codex CLI moves from the `live-completion-only` tier to `live-pre-and-completion`. One
  native-hook renderer now drives every hook-capable host from a single ordered chain, so
  Codex gets the entry-gate block, the plan-and-spec-before-code block, the decision-pause
  block, the rules-loaded block, the capability kernel, and the spoken completion verdict —
  the same guarantees as Claude Code, wired into `.codex/hooks.json` across all four
  lifecycle events (SessionStart, UserPromptSubmit, PreToolUse `^apply_patch$`, Stop).

  The same hook scripts run on both hosts; the host is one argv, never a fork. A single
  `edit-targets` extractor parses the edited paths from a Codex `apply_patch` (or a Claude
  `file_path`), so the gates and the stage writer are host-aware without duplicated parsing.
  `paqad-ai doctor` gains a `Codex hooks wired` check, and onboarding with `codex-cli` prints
  the one-time `/hooks` trust step. Gemini stays record-only and every advisory host is
  unchanged; the Claude and Gemini generated configs are byte-identical to before.

## 1.87.0

### Minor Changes

- 533cf1b: Require and evidence rule-loading for feature-development changes (#557).

  paqad enforced that the process ceremony ran (plan, spec, review, checks) but never that the
  project's rules were actually loaded — so an agent could complete a fully green change with
  every non-scripted rule unread, and code written on a non-feature route loaded no rules at
  all. Rule-loading is now a required, deterministic (no-LLM) part of any feature-development
  code change:

  - **`paqad-ai rules load`** prints the full text of the rules that apply to your changed
    files and writes `rules-loaded.json` into the feature bundle (which rules apply to which
    files, plus a content hash of the loaded text). It works on any route.
  - **Edit-time:** a new `rules-loaded` kernel capability blocks the first feature-dev source
    edit until that record exists — catching code written on a non-feature route at edit time.
  - **Completion:** a new gate fails a feature-dev change whose applicable rules were never
    loaded (the same way a missing plan or spec fails) and reads Inconclusive when the load is
    stale.

  No new config knob — rule-loading is required, gated only by paqad being enabled and the
  change being feature-development. The record attests that rules were loaded and acknowledged,
  not that they were comprehended.

## 1.86.0

### Minor Changes

- 13efb31: Make the feature-development `checks` stage fast without lowering the bar (#554, closes #505).

  The check runner now executes each mapped command as a quote-aware `&&` argv chain (in-process `mkdir -p`, no shell interpretation), captures stdout, and parses the test command into per-test results — so a profile command like `mkdir -p .paqad/test-results && ./vendor/bin/pest …` can no longer report green without running a test. The test suite runs with the runner's own parallel mode when the project has it (detected per runner from the stack pack and the ecosystem lockfile, recorded in the project profile and the stack doc, with a sequential fallback for small machines and harness failures — paqad installs nothing). Check commands are overlapped by a scheduler (formatters first, build before test, everything else concurrent), and every failure under parallel is confirmed alone before it blocks: fails-alone blocks with test name, file and line; passes-alone is quarantined in the flaky registry and never blocks. New `checks_parallel`, `checks_max_processes` and `checks_flaky_under_parallel` knobs, a doctor check, a `checks plan` / `checks record-runner` verb pair, and a Checks section on the feature report page. Everything at runtime is deterministic; no LLM call from Node.

## 1.85.0

### Minor Changes

- e5e56fc: feat(#551): PR visual evidence — screenshots of documented flows as feature-bundle evidence

  When a feature-development change touches frontend files, paqad now captures ordered
  screenshots of the documented user flows the change affects, pairs each with a
  business-language caption, stores them in the feature's git-ignored evidence bundle
  (latest-run-wins), assembles an overview GIF, and verifies the evidence at end-of-change
  like any other bundle artifact. Everything at runtime is deterministic scripts — zero LLM
  calls in the execution path.

  Off by default. Turn it on with the new `visual_evidence` flag (env `PAQAD_VISUAL_EVIDENCE`);
  `visual_evidence_mode` (`warn`|`strict`, floored) governs how firmly the gate enforces. With
  the flag off, feature-development is byte-identical to before.

  What is new when `visual_evidence` is on and a change is frontend-triggering:

  - a stack-pack `visual_evidence.frontend_globs` trigger decides when a change is frontend;
  - compiled capture scripts (`docs/site-map/journeys/<id>.capture.yaml`) derived from
    **confirmed** site-map journeys drive the capture;
  - a paqad-provisioned Playwright + Chromium runtime under `~/.paqad-ai/ve-runtime/` (never a
    hard paqad dependency, never imported from the target project);
  - per-step `image.png` + `caption.txt` and an `overview.gif` under the bundle's
    `screenshots/` subtree, with a bundle-integrity carve-out;
  - a `visual-evidence` verification gate, receipt line, and `report.html` section;
  - a `paqad-ai visual-evidence` CLI group (`run`, `plan`, `setup`).

## 1.84.0

### Minor Changes

- c6f611c: feat(#547): wire the spec pipeline and ship the domain experts

  The grounded prompt-to-spec pipeline and the expert plumbing were built but idle. This change
  starts the pipeline from the specification stage, gives eleven domain experts and a chief
  architect real behaviour, and records what every run costs and changes. It is off for onboarded
  projects by default; both flags stay off unless a project opts in.

  What is new when `spec_pipeline_enabled` is on:

  - The specification stage runs the pipeline. A shared instruction in the policy and the router
    says so, a new `spec pipeline start` verb grounds and labels the request in one go, and a new
    `spec_pipeline_adoption` knob (warn or strict) controls how firmly a hand-written spec is
    refused at freeze.
  - Eleven pickable experts and a chief architect become real through one `expert-notes` runner
    skill with a lens per expert and one `expert-synthesis` chief skill. The model decides which
    experts a request needs; the script only validates against the roster.
  - Each expert writes short request-time notes; the chief accepts or declines them, recommends a
    resolution for each disagreement (which becomes a decision you make), and lists what nobody
    covered. The spec is crafted with every line traced to its source, and the craft gate refuses
    an untraced requirement or an accepted finding that never reached the spec.
  - Freeze copies the run provenance into the record; the readable spec ends with a Provenance
    section; and every run records full metrics, with a `spec pipeline metrics` verb to read them
    back. A human's later edit to a frozen spec is captured by section.

  With the flags off, feature-development is byte-identical to before.

### Patch Changes

- 912d9e3: fix(#540): stop a background notification opening a change and orphaning a bundle

  A `<task-notification>` from a background monitor reaches a session as an ordinary user
  turn, and the extra `Stop` it produces made the marker parser re-read the whole transcript.
  With the previous change already closed, nothing was active, so every stale `paqad:stage`
  line read as unrecorded and a phantom untitled `change-<ULID>` bundle was opened for it —
  stealing the session pointer and failing its own completion gate, which turned a finished,
  green change into a red one.

  Three seams are fixed:

  - The prompt-routing seam recognises a host-injected system notification and treats it as
    no request at all, so a CI ping cannot re-route or clobber an in-flight change.
  - The retrospective marker seam refuses to open a bundle once the session has already
    closed a change. A session's first change is unaffected, including on the Codex and
    Gemini completion hooks that share the seam.
  - `paqad-ai resume --feature <ref>` now resolves a ref against the recorded bundles on
    disk as well as the session's paused stack, so a displaced change is reachable without
    hand-editing anything under `.paqad/ledger/`.

## 1.83.0

### Minor Changes

- 553c6db: feat(#538): keep the coding agent's vendor out of your commits and PRs

  An onboarded project used to inherit whatever attribution its coding agent adds by default:
  Claude Code appends a `Co-Authored-By: Claude` trailer and a PR body line, Cursor appends
  "Made with Cursor", and so on. That trailer is what makes a git host list the AI vendor as a
  **contributor** on the repository, which is the part an enterprise buyer rejects.

  paqad now owns this, behind one floored policy knob: **`ai_attribution`** (`keep` | `strip`,
  default **`strip`**). The team value is a floor, so a developer cannot quietly lower it.

  Onboarding configures the two providers that expose a project-level switch: Claude Code gets
  `attribution: { commit: '', pr: '', sessionUrl: false }` in `.claude/settings.json` (the
  current key, never the deprecated `includeCoAuthoredBy`), and Aider gets `attribute-author`,
  `attribute-committer` and `attribute-co-authored-by` set false in `.aider.conf.yml`. Both
  merge rather than overwrite, so a value the team set by hand survives.

  Cursor, Codex, Copilot and Gemini keep their switch in the developer's home directory or an
  org policy, which paqad will not write. For those, the delivery check is the backstop: at the
  completion seam it scans the branch's commit messages and the PR body and warns once per
  vendor found, carrying that vendor's exact fix. It is advisory and never blocks.

  paqad's own `Generated with paqad-ai delivery` footer is deliberately untouched by this knob,
  and a human colleague's co-author trailer is never matched.

## 1.82.1

### Patch Changes

- 19afcc6: fix(#528): re-home the checks report into the per-feature evidence bundle

  `paqad-ai checks run` now writes its structured report into the active change's bundle
  (`.paqad/ledger/feature-evidence/<change>/checks.json`, under the already-ignored `ledger/`
  tree) instead of the git-tracked global `.paqad/checks/last-run.json`, which was rewritten on
  every run and rode along as noise in unrelated PRs. The completion backstop and review digest
  read from the bundle with a global fallback for non-feature-dev sessions, `checks.json` is a
  registered (never hard-required) bundle file, and onboarding scrubs any previously-tracked
  `.paqad/checks/last-run.json` from git. No change to what the runner runs or to the report
  schema — only where it is stored and read.

## 1.82.0

### Minor Changes

- 1e369b2: feat(spec-pipeline): model-driven expert roster, off by default (issue #521, Phase 2)

  Adds the Phase 2 expert-roster machinery to the spec pipeline, gated behind the
  new off-by-default `spec_pipeline_experts_enabled` flag — with it off, zero Phase 2
  code runs and a pipeline run is byte-identical to v1 (P2-INV-1).

  The one design change from #521: the expert-need decision is made by a fast-tier
  agent-run skill (`expert-need-detector`), not a deterministic Node signal-scorer —
  a script cannot reliably tell which expert a request needs and would emit false
  signals. The model reads the request + the S0 grounding and returns a need artifact;
  the script only validates it against the roster (paqad calls no LLM from Node).

  What ships:

  - `EXPERT_ROLES` — the expert subset of the canonical `AGENT_ROLES`, budgets from
    `ROLE_TOKEN_BUDGETS` (no parallel roster).
  - `validateExpertNeed` / `validateExpertNotes` — reject any role outside the roster
    (AC-8) and any malformed artifact, so the model can never invent an expert.
  - Per-expert context-slice sizing that keeps every needed expert and only warns when
    the run token ceiling is exceeded — never drops one (AC-6/INV-5).
  - Conflict-aware merge: contradictory expert claims on the same target surface as a
    detected conflict rather than a silent pick (AC-9).
  - Per-expert accounting (which/why/tokens/whether it changed the spec, AC-5/AC-7),
    folded into finish provenance only when experts ran.
  - `paqad-ai spec pipeline experts record|notes` verbs (hard-gated on the flag) and a
    `doctor` coherence check for the expert config (FR-9).

  Enabling the flag and shipping a specific pilot expert stay gated on the FR-9
  measurement data (issue #521 AC-1); this change builds the machinery, off by default.

## 1.81.2

### Patch Changes

- fd71d26: feat(spec-pipeline): requirement-enrichment emits FR-4 two-layer question objects (B.5.2)

  The `requirement-enrichment` skill is the spec pipeline's S2 question-phrasing step (deferred from #512). It now emits the FR-4 two-layer question batch the `questions` step consumes — `{ questions: [{ business_text, why_it_matters, options[], grounded_in, technical_note? }] }` — instead of three flat markdown sections. It phrases on the cheap (`fast`) model tier, drawing vocabulary in priority order (S0 grounding terms → the user's prompt → plain English), with options phrased as outcomes not mechanisms and a `grounded_in` reference (or `null`) per question. The plain-language check stays the pipeline's job (`checkPlainLanguage`); the skill only phrases. `assets/output.template.md` and `scripts/lint-output.sh` were updated together to the new JSON shape.

## 1.81.1

### Patch Changes

- 1055da9: spec-pipeline: S0 grounding now has a RAG-on path (FR-2.1, deferred from #512). A new
  `groundAreaAsync` draws the touched area's vocabulary and references from the framework's
  existing semantic retrieval seam (`gatherWorkingSetSlices`) when `rag_enabled` is on, and
  falls back to the docs-glob `groundArea` when RAG is off or retrieval returns nothing. The
  pipeline builds no cache and no reader of its own — only the existing retrieval/cache is
  reused (FR-2.4 / FR-8.5). Grounding stays non-blocking (a thin area still succeeds and is
  marked `sparse`), and the grounding artifact now records which `path` it took (`rag` or
  `docs-fallback`). The `ground` CLI subcommand runs the RAG-aware path.
- 1055da9: spec-pipeline: the S4 crafting skill now reuses `edge-case-detection` to populate negative
  paths and non-goals (B.5.2 / FR-6.1, deferred from #512). `acceptance-criteria-gen` runs
  edge-case-detection as a sub-step and folds each surfaced scenario into a flat `AC-n`
  negative-path criterion (error/empty/permission paths) or into `## Non-goals` (deliberate
  exclusions). The rubric is reused, not cloned, and a new shared parity fixture proves a
  negative-path AC + non-goals spec passes both the S4 shape check and the freeze parser.

## 1.81.0

### Minor Changes

- 9216d33: Spec pipeline (#517): wire the deferred S2 ledger auto-answer step (FR-4.5). Before any
  clarification question reaches the user, the pipeline now checks it against the decisions
  ledger; a match injects the recorded answer with its source and the question never appears.
  It is a pure, zero-token lookup — paqad calls no LLM from Node.

  - New `src/spec-pipeline/auto-answer.ts` exports `autoAnswerQuestions(projectRoot, questions)`,
    returning `{ answered, remaining }`. Per question it consults two ledger seams in order:
    exact/fingerprint reuse (`findIntakePriorMatch` → `DecisionStore.findReusableDecision`) then
    advisory textual precedent (`findDecisionPrecedents`), accepted only above a high score floor.
    The rule seam (`resolveByCompiledRule`) is intentionally not wired — it is file-glob-triggered
    and cannot choose among plain-language outcome options.
  - `spec pipeline record questions` runs the batch through auto-answer and persists only the
    surviving questions plus the auto-answered list, so a ledger-answerable question never reaches
    the user.
  - The `questions.json` artifact widens to `{ questions[], auto_answered[], asked, answered,
deferred }` (the FR-7.6 counts); `validateStepArtifact('questions', …)` enforces it while
    keeping `questions[]` the only hard-required field, so a raw agent batch still validates.
  - `spec pipeline finish` feeds the auto-answered source ids and counts into `buildProvenance`,
    so the finish provenance lists the answer references — human input by reference, never a
    fabricated sign-off.

## 1.80.0

### Minor Changes

- 3067adb: Feature bundles are now provably complete. A finished feature-development change must leave every required file in its evidence bundle, and a missing one now fails the change instead of passing silently (issue #511):

  - `feature.json` finally has a writer — seeded when a feature opens and updated on rename / lane / spec-freeze / close, so a bundle records what it is instead of only its directory name.
  - `delivery.json` is seeded at open with the branch and base, so the first commit on a branch links; it also records a `commit_decision` (committed / declined / never asked) and reconciles from git at end-of-change.
  - A single declarative manifest states, per bundle file, when it is required and who writes it, guarded by a test so a future file cannot ship without declaring its expectation.
  - A new fail-closed `bundle-completeness` gate runs at end-of-change: under `bundle_completeness=strict` (the default) a required-but-missing/empty/invalid file reads "Needs your attention", naming the file and its writer, and blocks via the Stop hook. `warn` surfaces it without blocking; `off` falls back to the deprecated `evidence_existence_gate`. A cache-backfilled file is reported, never passed off as clean; non-feature / no-bundle / CI turns skip the gate.

- 018aac8: Spec pipeline (#512), Part A: every `spec freeze` now writes a human-readable
  `specification.md` beside the canonical `specification.json` in the feature bundle.

  - `specification.md` is a derived, read-only projection rendered from the frozen
    `FeatureSpec` on every freeze, so it can never drift and is never a second source of
    truth (the input-markdown deletion of #402 is unchanged).
  - Like `report.html` (#371) it is a non-member sibling: it is not a `FEATURE_BUNDLE_FILES`
    member, the exporter never parses it, and it is git-ignored by the managed `ledger/` line.
  - The fail-closed bundle-completeness gate (#511) now pairs the two: a bundle carrying
    `specification.json` must also carry `specification.md`, or the change fails closed under
    strict mode (surfaces as inconclusive under warn).
  - The `FeatureSpec` type and schema gain an optional, tolerant `non_goals` field (additive;
    specs authored without it still validate and freeze unchanged).

## 1.79.0

### Minor Changes

- dce2fc6: Rebuild the site-map workflow so it earns the trust it reports. The engine drafts the map
  skeleton from proven extraction instead of the model hand-typing it, detects navigation links
  from the code, records run progress so a new session resumes instead of restarting, batches every
  preflight question into one interruption, and reports an honest verdict (Safe to merge / Needs
  your attention / Inconclusive) when a map is absent or records no links. The dashboard gains a
  full-screen map, a readable zoom floor, and live run progress. As the first step, the compiled
  rule store is now recompiled automatically when it goes stale on the per-turn refresh path, and
  `paqad-ai doctor` reports rule-store freshness, so the agent is never served a rule that no longer
  matches the authored rules.

## 1.78.1

### Patch Changes

- a9db95e: Skip end-of-change enforcement and all completion checks when the session never
  routed to feature-development (#499). Previously a dirty working tree (for
  example a file hand-edited before the session) was swept up by the `git status`
  fallback, classified as a feature-development change by file path alone, and the
  in-session completion seam blocked the turn demanding planning/spec/review/checks
  stages the session never owed. The completion backstop now consults the per-message
  route: for a question, pentest, docs task, RCA, or small-talk session it runs no
  gate, mints no inferred-git record, writes no evidence, and never blocks — it
  returns an ok "verification not applicable" verdict and records one audit row.
  An absent/unknown route still runs the full pass (fail-closed), and a session that
  recorded any agent-authored code edit re-arms full enforcement. The git/CI
  backstop and the pre-mutation gates are unchanged.

## 1.78.0

### Minor Changes

- 2e48cdc: Enablement-first entry flow: the gate speaks the verdict and the bootstrap splits into a gate + a router.

  On a cold first turn the agent used to load the entire ~290-line `AGENT-BOOTSTRAP.md` — router, narration, stage protocol, and decision-pause contract — and narrate a workflow route before it had even checked whether paqad was enabled. Two fixes land:

  - **The prompt-gate states the verdict.** The Claude Code `UserPromptSubmit` gate already resolves enablement deterministically and stays byte-for-byte silent when paqad is OFF, so if its `[paqad]` directive fires at all, paqad is ON. The directive now says so as its first line and marks enablement a done step, so the agent spends zero tool calls re-checking it. The numbered load-step prose that was hand-duplicated in both entry hooks now lives in one shared `runtime/hooks/lib/agent-entry-directive.mjs` module, and the stale hardcoded workflow count is gone.
  - **The bootstrap splits into a gate + a router.** `AGENT-BOOTSTRAP.md` is now a ~23-line enablement gate (the precedence probe, the OFF bail-out, and a single "load `AGENT-ROUTER.md` when ON" pointer). The router, always-load list, sentinel, and the full narration and Decision Pause contracts move to a new `AGENT-ROUTER.md`, loaded only when enablement resolves ON. A disabled project never ingests any router or contract prose.

  Both files ship in the install directory and are reached through the existing entry-stub chain, so the split lands on every provider (Claude Code, Codex, Gemini, and the advisory hosts) with no entry-file or project churn. The enablement resolvers and the sentinel semantics are unchanged.

## 1.77.1

### Patch Changes

- 2a1597f: Fix: PreToolUse hooks no longer leak `{systemMessage}` into Claude Code Desktop chat

  The `capability-gate` and `stage-writer` PreToolUse hooks emitted a top-level
  `{systemMessage}` on their exit-0 (allow) path, on the now-false premise that a
  PreToolUse `{systemMessage}` is invisible on Desktop. Claude Code now renders it
  verbatim as `PreToolUse:<Tool> says:` lines — the same regression class as the
  `Stop says:` leak — spamming framework prose into chat on every edit. Both allow
  paths now emit nothing user-facing (the model speaks the narration; the ledger
  write is retained; the strict/blocking path is unchanged). The narration-contract
  channel table and the regenerated bootstrap are corrected to match.

## 1.77.0

### Minor Changes

- e262aaa: Rebuild the Site map dashboard canvas as an interactive city map (issue #489).

  On real, edge-sparse maps (this repo's own: 92 surfaces, 0 transitions) the previous
  canvas degenerated into an illegible vertical sliver, could not zoom to legibility, and
  leaked pinch-zoom to the whole page. The canvas now runs on React Flow 12 with a
  deterministic containment-first district layout of our own:

  - **Districts carry the structure.** Areas render as tinted district rectangles with a
    surface-card grid inside; a zero-transition map is a first-class citizen. Correct
    gesture substrate (cursor-anchored zoom, pinch, non-passive wheel, scroll-pans-by-default
    with a per-user setting, minimap) replaces the hand-rolled pan/zoom.
  - **Journeys are metro lines.** Each journey draws as a colored polyline through its own
    ordered stations (no transitions needed), with walk-mode camera flights, numbered
    stations, interchange rings, semantic-zoom levels of detail, and a cmd/ctrl+K search that
    flies to a surface, area, or journey. All motion respects `prefers-reduced-motion`.
  - **The map wears its verification state.** Trust tier changes a surface's rendering
    (solid/dashed/sketch, distinguishable without color), unverified surfaces sit under
    honest fog, and a payload-derived insight line plus a gaps chip surface dead surfaces,
    dangling targets, and broken journey references.
  - **Team-shared curation.** Districts are draggable; the arrangement persists to
    `docs/site-map/layout.yaml` through the dashboard's audited write path (refused in
    `--read-only`), and a stored district is pinned and never auto-reflowed.

  Everything still renders statically from `GET /api/site-map/map` with no LLM at view time;
  the #466 data model, detail panel, honesty strip, list toggle, and SSE live-reload are
  unchanged.

### Patch Changes

- d5059ce: Drop the `npm warn deprecated prebuild-install@7.1.3` warning shown on `npm install -g paqad-ai`.

  The warning came from the local-embeddings dependency `@xenova/transformers@2.17.2` (the last release under that scope), which pulled `sharp@^0.32` and its deprecated `prebuild-install`. Migrated to the renamed, maintained `@huggingface/transformers@^3.8.0`, which uses `sharp@^0.34` (no `prebuild-install`) and satisfies the `voyageai` peer range, so no new install warning is introduced. Model repo ids are unchanged and the pipelines pin `dtype: 'q8'`, preserving the previous quantized download size and embedding/rerank output.

## 1.76.3

### Patch Changes

- 457fcc0: fix(#472): reconcile the completion receipt so its headline and per-stage block agree

  The end-of-change receipt (#325) composed two independent subsystems without reconciling them: the verdict headline (`formatVerdictSummary`, driven by `verdict.ok`, computed from gates only) and the per-stage evidence block (the stage-evidence fold). A feature-development change whose gates all passed but whose mandatory `review`/`checks` stages had no evidence rendered a self-contradicting receipt — `Safe to merge / N/N checks held` beside `🟡 review/checks — not recorded`. It happened whenever a mandatory-stage gap did not flip `verdict.ok` (for example `stages_mode=warn`, where the stage-evidence gate is `skipped`).

  The receipt now reconciles **down** (the contract's own over-trust guard): when a feature-development change's gates all pass but a mandatory stage is not provably done, the developer-facing verdict word becomes **Inconclusive** and names the offending stages, so the headline agrees with the per-stage block. The true `🟢 N/N checks held for you.` line is kept, so gate evidence is still credited.

  `verdict.ok` stays gate-derived, so git/CI exit codes and warn-mode non-blocking semantics are unchanged — Inconclusive is "do not over-trust", never a hard block. (Defect 2, the #409 narration advisory, was already fixed by #476; this closes Defect 1.)

## 1.76.2

### Patch Changes

- 7ce4c34: fix: stop the `Stop says:` narration leak — silence Stop-hook `{systemMessage}` prose

  Claude Code changed how it renders Stop-hook output: a Stop-hook `{systemMessage}` now renders on Desktop as literal `Stop says:` lines, inverting the premise the #368/#409 narration design was built on (that the channel was invisible, so the agent speaks the receipt and the hook echo is a silent backchannel). With the host inverted, paqad's three Stop-event emitters poured user-facing prose into that channel on every turn, across every onboarded repo and machine — duplicating the receipt the agent already speaks and leaking the model-only narration advisory into the developer's chat.

  The Stop hooks no longer emit user-facing `{systemMessage}` prose:

  - `runtime/scripts/verify-backstop.mjs` (`hook-completion`): writes nothing on a pass/inconclusive turn and only a model-only `{decision:'block'}` reason on a hard failure. Enforcement is unchanged — the block reason reaches the model (never rendered on either host) and the git/CI backstop still hard-fails with exit 2.
  - `runtime/hooks/capability-gate.mjs` (`completion` seam): no longer echoes narration on the allow path; the `pre-mutation` (PreToolUse) seam is unchanged.
  - `runtime/hooks/stage-marker-parse.mjs`: still records every parsed marker to the ledger; only the chat echo is removed.

  The developer-facing channel is the agent's own final message (the #409 contract), which was always the intended primary channel. The narration contract docs and the verification module doc are corrected to state the new host behavior. Decision `D-01KZV9HFGDXZ03J0S6P9BTQ53Q` records the approach.

## 1.76.1

### Patch Changes

- 721b434: feat(#468): Phase C — writer cutover, retire the old evidence paths, add a warn-only existence gate

  Third and final PR of the #339/#468 evidence-in-bundle cutover — the only phase that changes the on-disk layout, now that both writers (Phase A) and readers (Phase B) are proven.

  - RAG (the deferred piece): the `runtime/scripts/rag-evidence-record.mjs` prompt seam and the TS recorder now write retrieval rows to the two-home `rag.jsonl` (the active feature's bundle, else `_chat/<session>/`), with the conversation ordinal re-homed to `_chat/<session>/`; the retired `paqad.rag-evidence/` substrate is gone. `foldRagEvidenceSession` reads `_chat` + the bundle projection (`readAllFeatureRag`) filtered by session.
  - Writer cutover: the completion seam stops the old-home writes — the `rule-evidence` project ledger, the top-level `evidence.jsonl` / `receipts.jsonl` / `receipt.dsse.json` / `ai-bom.json`, and the duplication/change-metrics project ledgers — keeping every engine cache (`report.json`, `drift.json`, `duplication.json`) and the per-feature bundle receipt/evidence. The reproducibility context stamp moves to `.paqad/session/context-stamp.json`. `src/rule-scripts/rule-ledger.ts` is retired.
  - Existence gate: a new `evidence_existence_gate=off|warn` knob (default `warn`, no exit-blocking tier) verifies the bundle's `rule-run.jsonl` / `duplication.jsonl` / `change-metrics.jsonl` / `rag.jsonl` exist backfill-first — minting the recoverable three deterministically from the caches (marked `backfilled: true`), and reporting an unrecoverable RAG absence as Inconclusive. Flag-aware: a flag-off / RAG-dark / copy-only / non-feature-dev change reads skipped, never a hard block. The gate runs at the completion backstop alongside the #394 plan/spec/review assertions and can only surface (pass/skipped/inconclusive), never fail.

- 721b434: Evidence-in-bundle cutover, Phase B (#468): re-point every evidence reader off the retired
  session-ledger and top-level homes and onto the per-feature bundle projections. The Rule
  Compliance collector reads findings from the bundle `rule-run.jsonl` (latest by `ts`) and
  drift live from the `.cache/drift.json`; the Change Shape collector and `metrics report`
  read the ts-sorted window of the bundle `change-metrics.jsonl`; the SIEM `audit export`
  aggregate unions the bundle projections and projects attestation/evidence from per-feature
  receipts; and the Trust panel (evidence feed, receipt feed, AI-BOM, attestation,
  onboarding, inventory) projects from the bundle union via `projectAiBomFromFeatures` and new
  per-feature receipt readers. The per-feature receipt now additionally carries the
  authorship/compliance/reproducibility predicates the attestation surfaces read, so a bundle
  receipt is a complete attestation record. The RAG session fold stays on the substrate in
  this phase: its re-point is coupled to the prompt-seam writer and moves with it in Phase C.
  No old-home write is removed and no path is retired — every old-home write still fires, so
  rollback is a single revert. Phase C removes the old writes and adds the existence gates.
- 9ff0f23: Evidence-in-bundle cutover, Phase A (#468): add additive per-feature bundle writers for duplication counts (`duplication.jsonl`), change-metrics ratios (`change-metrics.jsonl`), and the graded gate rows (`evidence.jsonl`), plus their whole-project projections. Every existing project/session-scoped write is left untouched — this is a dual-write parity window, not a cutover. A parity test asserts the new bundle rows agree with the old-home rows for a real feature-development change. No reader is re-pointed and no path is retired yet (Phases B and C).

## 1.76.0

### Minor Changes

- 2cbd0de: Begin the interactive visual site map (#466). The dashboard "Site map" area becomes an explorable, non-technical diagram of the app rendered statically from a single AI-authored YML at `docs/site-map/`, and creating the map is gated on the documentation family. This first slice lays the data foundation: an honest 5-level trust tier on every map element (surface, transition, guard, journey), a reader for the canonical `docs/site-map/` location, and a write path that stamps each element's earned trust tier into the stored map so the dashboard renders proven tiers statically with no work at view time. The `sitemap run` verb now wires that proof in: each run re-earns the canonical map's trust tiers and its map-vs-code freshness from the same code evidence it already resolves and writes them back when either moved, so the dashboard honesty strip and the freshness gate read earned proof instead of "not yet checked". The run now also reads the map and journeys it verifies from that same canonical `docs/site-map/` location, so it checks, resolves evidence for, and restamps exactly the map the dashboard renders rather than a separate copy. The one-step creation flow can now stamp each recorded answer's provenance back onto the surfaces it settled: a surface a person decided about reads as human-confirmed and a defaulted decision reads as a low-confidence guess, so the map is honest about which choices had a human behind them. That one-step creation flow now has a surface the agent can drive: `sitemap questions` lists only the closed-list questions the map still needs (with each question's plain reason, its `file:line` evidence, and a recommended default), and `sitemap answer` records the person's decisions to `docs/site-map/answers.yaml` and stamps their provenance onto the map in one step, so a settled human answer is never re-asked and a question whose code moved is reopened. The superseded report machinery is retired: a run no longer dumps timestamped reports under `docs/site-map/` or publishes derived index/overview/registry views under `docs/instructions/site-map/`, the `sitemap retest` verb and its dashboard action are gone (a re-run is simply the same run again), and the freshness gate now reads one deterministic signal, the map-vs-code freshness stamped into the stored map. The dashboard's Site map pulse section likewise reads the stored canonical map statically instead of the latest report dump. Everything stays inert while the `site_map` flag is off.

## 1.75.4

### Patch Changes

- 92b4710: fix(#205): never count generated `.paqad/` artifacts as changed code in verification

  When the runtime self-hosts, its generated artifacts land under a nested
  `.paqad/` home (`runtime/base/.paqad/`) that the root-only managed gitignore does
  not cover, so they leak into the working tree. The change-evidence classifier
  treated anything under `runtime/` as code, so the change-completeness gate demanded
  test evidence and doc updates for generated logs and evidence JSON. `isCodeFile`
  now excludes every `.paqad/` home (root or nested) via the new
  `isPaqadArtifactPath` predicate, and the verification changed-file scan strips
  `.paqad/` artifacts entirely, so they never reach `code_changed`, the test-evidence
  preview, the quality ratchet, or scope drift. (The invisible Stop-hook loop and the
  silent exit-2 from the original report were already resolved by #303/#368.)

## 1.75.3

### Patch Changes

- dc6976f: Reframe the security workflow copy to remove two overclaims (#206). User-facing text no longer calls the security pass a "full OWASP pentest" with "full OWASP coverage" or claims it proves code is "safe"; it is now described as an OWASP WSTG-structured security self-review that hardens code before a certified pentest, it does not replace one. Copy-only: workflow ids, routing patterns, the `pentest` invocation alias, and all code are unchanged.

## 1.75.2

### Patch Changes

- 36bcf08: fix(#450): `loadChangeEvidence` now reconciles the session change-artifact
  (`.paqad/session/changed-files.json`) against git before trusting it. A stale
  artifact left over from an already-delivered change (its files committed and
  clean in the working tree) is no longer attributed to a later, unrelated
  session — which previously forced the full feature-development stage gate and a
  `paqad-ai checks run` onto out-of-scope turns (e.g. a docs-only session). An
  artifact entry is now kept only when git still considers it part of the current
  change: dirty in the working tree, or committed on this branch since the
  merge-base with the base branch. When every entry is stale, evidence falls
  through to `git status`; when git cannot be read or has no base branch,
  behavior is unchanged (the artifact is trusted). The fix is at the shared
  `loadChangeEvidence` chokepoint, so every consumer (completion backstop, checks,
  RAG, duplication, rule-scripts) is corrected at once.

## 1.75.1

### Patch Changes

- c0edc5a: fix(#449): the completion (Stop) hook no longer forces the feature-development stage set on
  host-agent-config-only changes. Paqad's own host-integration directories (`.claude/`, `.codex/`,
  `.gemini/`, `.junie/`, `.cursor/`, `.windsurf/`, `.continue/`, `.aider/`, `.aiassistant/`) and the
  `.windsurfrules` entry file are now classified as non-feature-development in the scope predicate, so
  a session that only touches host wiring (e.g. regenerated hooks or an `mcp.json` edit) ends cleanly
  instead of hard-blocking with a false "missing stage-evidence" failure. `.github/` stays in scope
  (CI workflows are real code). Also fixes the #409 narration advisory so it only names stages the
  agent itself authored (`live-mark`/`redo`), never a hook/backstop-inferred stage the agent never
  claimed.

## 1.75.0

### Minor Changes

- ca8aefa: **Site map is a dashboard area now, not a command you type (#448).** Open `paqad-ai dashboard`
  and there is a **Site map** entry in the side menu: it shows the latest run (surfaces, journeys,
  findings, skipped checks) and a **Run site map** button that maps the app on demand. The run is
  the same deterministic, zero-token audit the engine always did — it just happens from the web,
  with live progress and a dashboard-attributed line in the audit trail, so no one has to drop to a
  terminal.

  The `paqad-ai sitemap` verb still exists for CI and scripting, but it is now hidden from `--help`
  (the dashboard is the place to run it), mirroring how `graph` became a dashboard area. Everything
  stays behind the OFF-by-default `site_map` flag.

- ca8aefa: **Site map dashboard: Retest and journey sign-off from the web (#448).** The Site map area now
  carries the last two actions that used to need the terminal:

  - **Retest** replays the latest run against the current code (a `site-map-retest` dashboard
    action, with live progress). If there is no prior run to replay it says so instead of failing
    obscurely.
  - **Journeys** lists the app's journeys and lets you **Confirm** or **Reject** the proposed ones
    in place. Confirming makes a journey part of the map; rejecting drops it. Both run the same
    audited curation the engine always did.

  The run itself is unchanged. Everything stays behind the OFF-by-default `site_map` flag, and the
  `paqad-ai sitemap` verb remains available (hidden) for CI and scripting.

### Patch Changes

- ca8aefa: **Fix (#448): a legacy `.paqad/doc-progress.json` no longer blocks a site-map run.** Site-map
  publication used to piggyback on the documentation workflow's `DocumentProgressTracker`, so every
  `sitemap run` loaded and schema-validated `doc-progress.json` — and a file written by an older
  paqad (an unrelated, disjoint shape) threw, aborting the run before `index.md` / `overview.md`
  were published.

  Site-map now keeps its **own** differential-refresh ledger at `.paqad/site-map/progress.json`
  (schema-versioned, mirroring the tolerant persistence of the code-knowledge index: a missing,
  corrupt, or schema-invalid file degrades to empty and self-heals on the next run rather than
  crashing). Nothing under `src/site-map/` reads or validates `doc-progress.json` anymore, so an
  unrelated stale ledger can never block a map publication or the site-map freshness gate. The two
  concerns are decoupled by construction. All behaviour stays behind the OFF-by-default `site_map`
  flag.

## 1.74.0

### Minor Changes

- f51816a: **Site Map — framework-native Laravel surface extraction** (behind the OFF-by-default `site_map`
  flag). The dedicated extractors now ask the framework instead of grepping fixed directories:

  - **Artisan-first routes** — `paqad-ai sitemap run` runs `php artisan route:list --json` when it
    can, so modular routes (`nwidart/laravel-modules` and bespoke `Modules/*/Routes/` layouts) are
    mapped through the real router, route middleware is carried as guard hints, and each surface is
    attributed to its owning module from the controller namespace. When artisan cannot run (no PHP,
    or the app will not boot) the run degrades to a modular-aware static route scan and records a
    labelled blocked check — never a crash, never a silent pass.
  - **New non-HTTP surfaces** — artisan/console commands (`php artisan list`) become `cli-command`
    surfaces, scheduled tasks (`php artisan schedule:list`) become `job` surfaces, and a
    modular-aware static scan maps queued jobs (`ShouldQueue`) to `job` surfaces and mailables /
    notifications to `email` surfaces.

  Artisan is best-effort, timeout-bounded, and read-only (`route:list`, `list`, `schedule:list`).
  The pure mappers and parsers are at 100% branch coverage; the shell-out and file globbing live in
  the coverage-excluded gatherer.

## 1.73.0

### Minor Changes

- 3b5bc7b: Three follow-ups to the **Site Map** capability, all behind the OFF-by-default `site_map` flag:

  - **Dedicated React + Laravel route extractors** — `paqad-ai sitemap run` now maps real web apps
    with high-confidence surfaces (React Router routes → pages, Laravel `Route::` declarations →
    page/api by uri), instead of only the generic convention fallback. Unknown shapes still fall
    through to the fallback, never a guess.
  - **Dashboard Site map area** — the dashboard gains a scored "Site map" section (surfaces,
    journeys, open findings, freshness) built from the published run sidecar, so the map is visible
    rather than only files.
  - **Journey curation** — `paqad-ai sitemap journey confirm|reject <id>`, the human sign-off that
    turns a proposed journey into a confirmed one (or removes it), recorded on an audit ledger. The
    code never self-confirms.

## 1.72.0

### Minor Changes

- 12acee3: New **Site Map** capability — the deterministic core (P1), behind an OFF-by-default `site_map`
  flag (env `PAQAD_SITE_MAP`). With the flag off nothing changes; when on and the coding capability
  is active, `paqad-ai sitemap run` maps the application — its surfaces (pages, screens, endpoints,
  CLI commands), transitions, guards, and areas — reconciles them against a canonical
  `docs/instructions/site-map/app-map.yaml`, runs Tier-A verification (evidence resolution,
  cross-reference integrity, graph invariants), and publishes a token-budgeted `index.md`, a
  deterministic Mermaid overview, and screen/API registries. Zero model tokens: the engine mirrors
  the codebase-health pattern (injectable gatherer → pure assemble → exit-code-as-verdict).

  This release wires the capability into the framework:

  - **Routing**: `site-map` and `site-map-retest` are routed workflows (mirroring
    codebase-health / health-retest). Verb-qualified triggers keep a literal `sitemap.xml` feature
    request on the feature-development path.
  - **Skills, roles, and rules**: the `site-map` / `site-map-retest` workflow rules, the
    `app-cartographer` and `journey-designer` agent roles, and the fine-grained skills (readiness,
    extraction, modeling, transition-tracing, guard-inference, assembly, verification, gap-analysis,
    publication, maintainer, retest, and journey-synthesis). Journeys are proposed by
    `journey-synthesis`/`journey-designer` and become `confirmed` only through human sign-off.
  - **Freshness gate**: a feature-development change that drifts the map cannot reach "Safe to
    merge" while a published view is stale — inert unless the flag is on.
  - **Retest**: `paqad-ai sitemap retest` replays a prior report by stable `SM-` id (never invents a
    finding, never lowers severity, never calls the absence of proof a fix).

  The React dashboard Site map area and the human journey-curation UI (confirming a proposed journey)
  are deferred to a follow-up.

## 1.71.0

### Minor Changes

- b394371: Framework-native reuse now covers PHP/Laravel, Python and Java/Spring, not just JS/TS
  (#398). Each ecosystem gets an adapter behind the same normalized schema: resolve the
  version actually installed, read the declaration layer that ships with it, and answer
  whether a symbol exists and whether it is deprecated — so `plan compile` checks a Laravel,
  Django or Spring reuse claim exactly as it already checked a React one.

  Laravel facades resolve through their `@method static` docblocks rather than reporting
  `__callStatic`, and the version-pinned Laravel Upgrade Guide is folded in as a
  `doc-derived` deprecation backstop for the deprecations Laravel documents but never tags.
  Metaprogrammed members always read "could not verify statically", never a false "does not
  exist".

  `FRAMEWORK_PACKAGE_MAP` also gains the Spring Boot, Django, FastAPI and Rails coordinates
  it was missing, so those projects are detected and indexed instead of silently producing
  nothing.

## 1.70.0

### Minor Changes

- 39f86ea: Verify framework reuse claims against the version you actually have installed (#397).

  A plan could already declare it was reusing a framework API — "I'll use React's `useId()`
  instead of hand-rolling one" — but nothing checked the claim. Now paqad reads the
  declaration files shipped inside the installed package and answers two questions before
  the plan compiles: does that symbol exist at your installed version, and is it
  `@deprecated`? A plan naming a removed API fails with the nearest existing symbol; one
  naming a deprecated API fails citing the deprecation message. No AI, no network.

  New: `paqad-ai index framework-api build` and `paqad-ai index framework-api query
<package> <symbol>`.

  Nothing new is installed for this. `typescript` is an optional peer dependency resolved
  from your own project, so a Laravel, Flutter, or Python project pays nothing for a
  JS-only check, and a project without it degrades to a visible warning rather than a
  block. Anything paqad cannot verify statically — a dynamically-provided member, an
  unindexed package, a missing index — warns instead of failing, because a false "this
  does not exist" would block a perfectly good plan.

## 1.69.0

### Minor Changes

- 09ef89f: Prove "less, better code" with per-change shape metrics (#362).

  Two deterministic, diff-scoped, zero-model-token numbers are now computed for
  every feature-development change:

  - **duplication on new code** (`dup_new_pct`) — the % of the change's meaningful
    new lines that near-duplicate existing code, folded from the #358 duplication
    cache.
  - **reuse rate** (`reuse_rate`) — cross-file calls from the change's new code
    into pre-existing, untouched files per 100 changed lines, from the #353
    code-knowledge index.

  They fold over caches the completion gates already produced (no second scan) and
  surface everywhere the developer already looks: one honest `change shape` line on
  the end-of-change receipt, a metrics block on the feature bundle receipt, a
  `change-metrics` row on the session ledger (which flows into the SIEM export), a
  new **Change Shape** dashboard trend section with bands (green 0–3%, amber
  3–10%, red >10%), and a new `paqad-ai metrics report` verb that prints the last N
  changes offline. Either metric degrades to `n/a` when its source cache is absent.
  Controlled by the `metrics_enabled` config knob (default on; respects the global
  disable).

## 1.68.0

### Minor Changes

- 9f35bb7: Arm the create-vs-reuse decision pause from evidence instead of the agent's
  honesty (#361).

  The `create-vs-reuse` pause used to fire only when the model volunteered that
  it was at a reuse fork, and the packet's `callers` / `similarity` evidence
  fields were computed by nothing. Now the framework mints that packet itself,
  with the proof filled in, on two deterministic triggers:

  - **Plan time:** at `plan compile`, each declared `new_constructs[]` entry is
    scored against the code-knowledge index (#353). A name/spec similarity at or
    above `decision_arm_plan_threshold` (default 0.85) opens a `create-vs-reuse`
    packet whose reuse option carries `{ file, last_modified, callers, similarity }`
    and whose create-new option carries the plan's own justification. The
    recommendation is reuse once the existing symbol has at least three callers.
  - **Change time:** a blocking-band duplication finding (#358) opens the same
    packet from the finding, through one shared minter.

  Both mints go through `paqad-ai decision create` (never hand-authored JSON),
  carry `origin: "evidence-armed"`, and honour a `decision_arm_max_per_change`
  cap (default 1 — only the strongest fork is asked; the rest surface as warnings).
  An identical fork already answered under `.paqad/decisions/resolved/`
  auto-applies that prior answer instead of re-asking and records
  `reused_decision:<id>`. The `ContractDecisionOption` shape gains an optional
  `evidence` field (additive, backward-compatible) so the pause gate and existing
  packets are unaffected.

  Governed by `decision_arm_mode` (off | warn | strict, team value is a floor):
  `warn` (default) reports the fork without minting; `strict` opens the blocking
  pause; `off` is identical to prior behavior. With the code-knowledge index
  absent, plan-time arming no-ops silently.

## 1.67.0

### Minor Changes

- 7aaebd3: Give the review stage hard facts, and make ignoring them detectable (#360).

  `paqad-ai review digest` composes `.paqad/session/review-digest.md` from what
  paqad already computed — rule-script findings, duplication findings, the check
  verdict, failing verification gates — alongside the frozen acceptance criteria,
  the per-stage state, and an honest list of the blind spots no machine covers.
  It reads cached JSON only: no subprocess, no scan, no model tokens, hard-capped
  at 150 lines.

  The review stage contract now tells the model to build and read it before
  writing findings, and `ImplementationReviewGate` fails when a deterministic,
  file-anchored, high-severity finding is never cited by `file:line` in the
  recorded `review.json`. The gate re-derives those rows from the same collector
  the digest uses, so skipping the verb does not disarm the check. A change with
  no machine findings behaves exactly as before.

## 1.66.0

### Minor Changes

- 87c8153: Wire the idle planning skills into the enforced stage contract (#359): four fully-built-but-never-invoked planning helpers now run when relevant, and only when relevant.

  - The enforced feature-development **planning stage** gains three lane-gated instruction blocks, sourced from one shared set of constants so the default policy object and the rendered `feature-development.yaml` cannot drift: an all-lanes reuse reflex (consult the Existing surface + `index query`, follow the solution-architect Reuse / Extend / Build-new procedure), a graduated/full block that runs `diff-minimizer` before the plan compiles and `existing-doc-checker` before any new doc, and a graduated/full multi-module block that runs `cross-module-impact-scanner`.
  - **Lane honesty:** a fast-lane change pays exactly one sentence; no skill procedure loads for it. A new `reusePlanningInstructions(lane, { multiModule })` assembler is the single source of that lane-gating logic.
  - The #357 plan schema now accepts an optional per-step `classification` (`ac-satisfying` | `necessary-setup` | `scaffolding` | `over-build`) so a diff-minimizer verdict can ride in the compiled `plan.json`; a plan without it stays valid.
  - No new hook and no new runtime gate — the skills feed fields the schema already checks, and the wired-vs-sidelined map in the onboarded-project overview is updated to keep it honest.

## 1.65.0

### Minor Changes

- 2d1bdbe: Add the duplication gate (#358): a deterministic, new-code-only detector that flags when a change introduces code near-copying something the project already has, before the change is called done — and stays quiet on legacy duplication it did not cause.

  - Zero model tokens: pure token-shingle computation over the existing chunk index, with a fallback that works even when no embedding index is present.
  - Binds at the verification backstop (a `duplication` gate whose verdict lands in the end-of-change receipt) and ships a `paqad-ai duplication scan [--json]` CLI verb.
  - New knobs `duplication_mode` (off | warn | strict, default warn for a two-cycle bake-in), `duplication_similarity_threshold` (default 0.90), and `duplication_min_lines` (default 8).
  - A blocking finding can be accepted through the existing create-vs-reuse Decision Pause; the resolved packet unblocks it and is noted in the report.
  - Consolidates three near-identical private cosine implementations into one canonical `cosineSimilarity` helper.

## 1.64.0

### Minor Changes

- f99e23e: Plans must now declare reuse (issue #357). `paqad-ai plan compile` requires a `reuse` section recording what existing code was consulted, what the plan will reuse, and why anything new is justified — so a plan can no longer quietly rebuild something the project already has.

  The enforcement is deterministic schema validation inside the existing compile verb, costing zero model tokens. First-party reuse claims are cross-checked against the code-knowledge index (an unknown symbol fails with a nearest-match suggestion), and framework-native claims are cross-checked against the resolved stack snapshot. Every check degrades gracefully: a missing index or stack snapshot downgrades the check to a warning rather than blocking, and a project with no detected framework carries no new burden.

  The end-of-change receipt's planning line and the per-feature HTML report now surface the declared reuse counts. Existing `plan.json` files stay valid and readable — the section is required on the compile-input side and optional in the stored schema.

## 1.63.4

### Patch Changes

- f2128be: Make feature-development stage narration visible on Claude Code Desktop (#409).

  The stage hooks narrate on Claude's `{systemMessage}` channel, which the Desktop app
  records as a hook attachment and never renders in the chat. A verified six-stage run
  emitted eleven `▸ paqad` stage lines and the developer saw none of them, while the
  evidence bundle was complete — recorded but unnarrated, the inverse of #389.

  The narration contract now tells the Claude Code agent to speak its own stage lines and
  the one end-of-change receipt in visible assistant text, placed in the turn's final
  message, and carries a per-surface table of which channels actually render instead of
  the previous single wrong assumption. A new deterministic backstop reads the turn
  transcript and reports any stage recorded this turn with no matching visible narration,
  advising the model to relay the receipt. The check is advisory: it never turns a passing
  verdict into a failing one and never blocks a turn.

## 1.63.3

### Patch Changes

- eb1fa9a: fix(#401): spec freeze now runs the spec-quality review it always claimed to require

  `paqad-ai spec freeze` told you, in both the rule pack and the workflow contract, that
  freezing enforces "no critical spec-review defects". It never did: the CLI evaluated the
  freeze with no review attached, so that clause was enforced nowhere. Agents closed the gap by
  hand-running `compliance review`, which left a stray `.paqad/compliance/<slug>/spec-review.json`
  behind that was neither part of the change's evidence bundle nor git-ignored.

  Freeze now runs the review itself and blocks on a critical defect like any other blocker, so
  there is no second command to run and no stray artifact. On a clean freeze the defect summary
  is folded into the bundle's `specification.json`, so the review evidence travels with the spec
  of record. Non-critical findings never block.

  Two related fixes: `spec freeze` and `compliance review` now reject a spec file that resolves
  outside the project root and record `spec_file` as a project-relative posix path, and the
  managed `.paqad/.gitignore` covers `compliance/` so a compliance artifact can never surface as
  an untracked, committable file.

## 1.63.2

### Patch Changes

- 462e891: Keep one change in one evidence bundle when the session id rotates mid-change (#404).

  The active feature is tracked per session, so when the host session id rotated partway
  through a change — an app relaunch, a resumed conversation, a rotated `SE_SESSION` — the
  new session read a fresh control, found nothing active, and minted a second
  `change-<ULID>`. The bundle the change was already recorded in got orphaned, and the
  stages recorded before the rotation had to be re-recorded by hand.

  A session's control is now reconciled before anything mints: when its active pointer
  names no evidence, it is repointed at the in-flight bundle **for the current branch**.
  This runs on both the write and the read paths, and from the SessionStart hook so a
  rotation is carried over before the agent records anything. It never mints a bundle,
  never adopts when two or more changes are in flight on the branch, and never resumes a
  feature the session paused.

  The branch is what makes this usable. "In flight" alone means real stage rows and no
  close row, and that set only grows — an abandoned change and a change shipped without a
  passing verdict never get a close row either, so a real repo accumulates them (this one
  held 13). Scoped that way, an "exactly one in flight" rule could never fire. A session id
  rotates within a change and a change is built on one branch, so the branch identifies the
  rotated session's own work, with no clock heuristic and no tunable window. The branch is
  stamped on the bundle's `open` row and falls back to the branch `delivery.json` already
  recorded; a bundle with no knowable branch is never adopted while on one.

  `closeActiveFeature` also stamps a `close` row on the bundle now. Releasing one session's
  pointer was previously the only record that a change had finished, which no other session
  could see — so adoption would have resurrected it.

## 1.63.1

### Patch Changes

- 2d4f101: fix(#403): back-fill the generic `change-<ULID>` bundle slug from the plan title. When `plan compile` writes a titled plan into a feature whose dir was minted by a bare `paqad:stage planning start`, the bundle is renamed to its descriptive `[<issue>-]<slug>-<ULID>` name — same ULID, every `_session` control repointed, stage-evidence artifact paths rewritten and re-stamped. The feature-development rule pack now tells the agent to include the change title in the plan template.

## 1.63.0

### Minor Changes

- 9008ec6: Keep the feature evidence bundle rigid-only, and give the review stage a real artifact.

  A feature bundle directory is meant to hold only rigid, script-owned artifacts, but
  nothing enforced that. The `review` stage owned no bundle file at all, so its evidence
  was an agent-authored markdown file written wherever the model chose — and the HTML
  report actively went looking for one, which is how a stray `review-notes.md` and a
  duplicate copy of the spec ended up sitting beside the rigid JSON.

  - New `paqad-ai review record <template.json>` writes a rigid, schema-validated
    `review.json` into the active feature's bundle, the review stage's counterpart to
    `plan compile` and `spec freeze`. A `review` stage-end that names anything else now
    records inconclusive.
  - No stage may prove itself with a non-rigid file written inside a bundle directory,
    and `paqad-ai feature export` reports any stray files it finds.
  - `paqad-ai spec freeze` now deletes its transient spec markdown on success (pass
    `--keep-input` to keep it) and refuses a spec authored inside a bundle directory.
  - The feature report renders the review from `review.json` instead of reading a
    free-written markdown file.

## 1.62.0

### Minor Changes

- 0cd07f4: Add `paqad-ai join` for zero-diff teammate setup, persist onboarding RAG choices in tracked team configuration, and make repeat onboarding manifests byte-stable.

## 1.61.1

### Patch Changes

- 496950a: fix(#394): feature-development plan/spec must land in the feature bundle

  A feature-development change could produce correct code yet write its plan and spec
  to an invented `.paqad/features/<slug>/` directory, never creating the bundle's rigid
  `plan.json` / `specification.json`, while the stages still read green. Three fixes
  close that:

  - **Rules (RC-1):** the feature-development rule pack and requirement-analyst agent now
    instruct `paqad-ai plan compile` / `paqad-ai spec freeze` into the bundle and no longer
    name `.paqad/plans/*` or `.paqad/specs/*` as durable write targets.
  - **Enforcement (RC-2):** a `planning` / `specification` stage-end whose artifact is not
    the active bundle's `plan.json` / `specification.json` is recorded inconclusive (the
    artifact is dropped so no digest is hashed), with a message naming the compile/freeze
    verb. `review` and the mutation stages are unchanged.
  - **Verdict (RC-3):** the end-of-change completeness verdict now asserts the bundle
    actually contains a non-empty `plan.json` and `specification.json`; missing either
    reads incomplete / Needs your attention, never Safe to merge.

  The dogfooded fix produced both artifacts in its own feature bundle, and no
  `.paqad/features/` directory was created.

## 1.61.0

### Minor Changes

- 9467f47: feat(#389): imperative advisory-host stage protocol + honest JetBrains tiering

  The JetBrains Claude Agent incident (framework followed, but stages unenforced and
  the ledger empty of planning/specification artifacts) exposed that on advisory hosts
  paqad had zero enforcement and relied on the model voluntarily self-recording. The
  bootstrap only said "narrate every stage and the verdict yourself" — too weak. The
  advisory-host section now imperatively requires running the host-independent CLI for
  a feature-development change: `paqad-ai stage start/end`, `paqad-ai plan compile`, and
  `paqad-ai spec freeze`, in order, so the stage-evidence ledger carries real planning +
  specification artifacts even where no lifecycle hook fires.

  The verification-enforcement doc now documents the three JetBrains products honestly:
  **Claude Agent / AI Assistant** reads `CLAUDE.md`-equivalent guidance but fires no
  Claude Code hooks (advisory — the incident's host), the **Claude Code [Beta] plugin**
  runs the real `claude` CLI so paqad's hooks fire (full, hook-enforced — the supported
  enforcement path), and **Junie** is advisory. The `aiassistant` adapter (already
  correctly `hooks:false`) is now listed in the per-adapter coverage matrix, and a
  reproducible manual advisory-host protocol is documented. No host-detection change and
  no overclaim of enforcement paqad does not have on the host.

- 9467f47: fix(#390): gate feature-evidence bundle creation + report render to the feature-development route

  Feature-evidence artifacts — the `feature-evidence/change-<ULID>/` bundle,
  `stage-evidence.jsonl`, `report.html`, `receipt.json`, `ai-bom.json`, `rag.jsonl`,
  and `_session/<id>.json` — were created for **every** workflow, not only
  feature-development. A `root-cause-analysis` (or any non-feature) session that emitted
  `paqad:stage` markers and reached Stop still minted a `change-<ULID>` bundle and a
  `report.html`, because both the marker-driven auto-open and the report/receipt render
  gated only on "is a feature pointer active?" (`currentFeature() != null`), never on the
  routed workflow.

  Both seams now consult the **persisted route** via `isFeatureDevelopmentRoute` (a new
  `routeIsAffirmativelyNonFeature` helper), not the working-tree diff:

  - `parseAndRecordMarkers` records nothing when the route is affirmatively
    non-feature-development, so no bundle or `_session` control is minted.
  - The per-feature receipt/AI-BOM projection and `renderActiveFeatureReport` in
    `run-repository-verification.ts` write nothing when the route is affirmatively
    non-feature-development, even if a pointer leaks through.

  **Cross-provider safe by design:** suppression fires **only** on a route we can prove
  is non-feature. The route seam runs only in Claude's UserPromptSubmit hook, so
  Codex/Gemini sessions — which record markers through the same recorder but never write
  route state — have **no** route state; an absent route is treated as "unknown" and
  preserves today's recording behaviour rather than silently killing all cross-provider
  feature-evidence. Feature-development behaviour is unchanged.

- 9467f47: feat(#388): stop auto-opening report.html in the browser and remove the `feature_report_auto_open` config option

  The per-feature `report.html` no longer opens in the OS browser. The auto-open-on-completion
  path (fired by the completion hook) and the manual `paqad-ai feature report --open` path are
  both removed, and the sandbox-aware opener (`report-open.ts`) is deleted — no code path opens a
  browser anymore.

  **Removed config key:** `feature_report_auto_open` is gone from the config registry, resolver,
  serializer, listing, the project-profile type and JSON schema, the onboarding default seed, and
  the generated config templates. On the next onboard/update the config-split reconcile (#227)
  prunes the key from team/local `.config.*` files, so existing projects stop opening the browser
  without manual edits — every still-valid value is preserved.

  Report **generation** is unchanged: the `feature_report` flag (default on) and
  `renderActiveFeatureReport` still write `report.html` into the feature bundle exactly as before.

### Patch Changes

- 9467f47: fix(#387): reject sequential decision ids at write, migrate legacy fixtures

  Decision packets could still be minted with sequential `D-{number}` ids when an
  agent bypassed the sanctioned writer and hand-authored the JSON, seeded by legacy
  `D-1`/`D-2`/`D-3` example packets. The creation paths now funnel through a single
  canonical `D-<ULID>` guard — `DecisionStore.writePending` rejects a caller-supplied
  non-ULID id, and `createPendingDecision` already mints one — while read, validate,
  and list stay tolerant of legacy ids so pre-existing packets keep working. Onboard
  and update now best-effort migrate any `.paqad/decisions/{pending,resolved}/D-{N}.json`
  to a minted ULID id (updating the in-file id and index reference, idempotent on
  already-ULID packets), the repo's own legacy fixtures are migrated, and the bootstrap
  now states imperatively that packets are created only via the `decision` skill,
  never by hand — including on advisory hosts with no Decision-Pause hook.

- 9467f47: Close two CodeQL high-severity findings surfaced on the evidence/decision paths:

  - **Resource exhaustion (`js/resource-exhaustion-from-deep-object-traversal`)** — `SchemaValidator` no longer sets ajv `allErrors: true`, so validation short-circuits at the first error instead of traversing an entire (potentially deeply nested, caller-influenced) object to collect every error. `verbose` is retained so error output still carries the offending value; results now report the first failure rather than all of them.
  - **File-system race (`js/file-system-race`)** — the legacy decision-id migration's `remapIndex` dropped its `existsSync` check-then-`writeFileSync` sequence, which was a time-of-check/time-of-use race. It now relies on the existing `try/catch` (a missing index throws `ENOENT`, treated as "nothing to remap"), with identical behaviour and no race window.

- 9467f47: fix(#386): batch onboarding's git check-ignore to a single call

  Repository discovery spawned two synchronous `git check-ignore` subprocesses per
  visited directory, so onboarding stalled for seconds before the provider prompt on
  large repositories. It now walks the tree once into memory and resolves all
  git-ignored paths with a single batched `git check-ignore` call, cutting spawns
  from O(directories) to O(1) with identical detection output.

## 1.60.2

### Patch Changes

- 3900daf: Prevent onboarding repository discovery from scanning dot directories, ignored paths, generated trees, and nested Git checkouts.

## 1.60.1

### Patch Changes

- 54d949b: fix(#380): stage-integrity fixes from the 1.59.0 #356 dogfood RCA

  Two deterministic stage-evidence defects surfaced by the #380 RCA are fixed:

  - **Orphan feature bundle ("bug #5").** The SessionStart hook now aligns the
    machine-local ledger-session cache to the live host session id. Previously the
    single-slot cache could still hold a prior session's id at the start of a new
    session, so a shell `paqad-ai stage start --title` invoked before the first edit
    minted its feature bundle under a stale session while the PreToolUse gate keyed on
    the true host session — orphaning the bundle and blocking the first edit. This
    extends the bug #5 mitigation from finalization to bundle minting.
  - **`documentation_sync` left start-only.** `recordMarkedStage` now forward-closes any
    earlier still-open stage before opening a marked (non-mutation) stage, symmetric with
    the live edit writer. Previously the last mutation stage (e.g. `documentation_sync`)
    had no later mutation edit to close it, so a following marked `review` stage opened
    without closing it and the change was left with a dangling open stage.

## 1.60.0

### Minor Changes

- 2b2ee2c: Planning now sees the codebase: on the feature-development route, the background context
  worker composes a token-capped `## Existing surface` section into the session-context
  artifact. It lists the exported symbols that already exist for the files/modules the prompt
  and working set implicate — as signature cards (`name(signature) — file:line · called from N
places · module`) ranked by the repo-map's structural importance (PageRank) — so the model
  reuses what exists instead of rewriting it. Signatures and caller counts come from the
  code-knowledge index when present, falling back to name-only cards otherwise. The section is
  budget-capped (config `existing_surface_tokens`, default 1000) with an honest truncation
  line, appears only for feature-development (every other route stays token-neutral), and rides
  the existing artifact so Codex/Gemini/advisory hosts get it through the same file. This gives
  the built-but-unconsumed repo-map its first live consumer.

## 1.59.0

### Minor Changes

- deb1cb9: Make the end-of-change verdict visible, honest, and enforced (#368). The completion backstop now surfaces the one end-of-change receipt to the developer whether the verdict passes, fails, or is inconclusive — a failing "Needs your attention" verdict can no longer be hidden on stderr while a PR ships. A hard-failing feature-development change now blocks the turn at the Stop seam via the documented `decision:block` channel (exit 2 is a no-op there), bounded by the stop-hook loop guard. A feature-development change with no real `paqad-ai checks run` report reads as Inconclusive and shows its `checks` stage as unverified rather than done. The `checks.block_on_failure` escalation stays script-enforced; `review_findings` / `stale_docs` are documented as agent-raised and Decision-Pause-enforced rather than falsely claiming script enforcement. The cross-provider verdict tiering (hook-surfaced on Claude, agent-narrated on Codex/Gemini/advisory) is documented so the promise is truthful per host.

  Also (AC-D2, from the second reproduction on the #355 session): the evidence receipt's `verification_result` is now three-way — `FAILED` only on a genuine failure, `INCONCLUSIVE` when a measure could not run (a `blocked` ratchet from unwired/absent tooling) or could not be judged, and `PASSED` when every row passed. A couldn't-verify is no longer reported as a failure, so an unwired quality-ratchet measure can no longer manufacture a false `FAILED` on the attestation.

## 1.58.0

### Minor Changes

- ee46d89: New routed workflow #10 **codebase-health** (backed by **health-retest**): a project health check-up on demand, at the same tier as pentest and design-test. Say "check my project's health" and paqad scans for six kinds of junk — dead code, unused packages, outdated or risky packages, leaked secrets, stale docs, and copy-paste AI slop — and lands every finding in one report with proof (real tool output, never an AI opinion), a plain-words reason it matters, and what to do about it.

  Detection is a single deterministic verb, `paqad-ai health run`, that costs zero model tokens: it reuses the code-knowledge index (dead code, unused deps), the 9-ecosystem dependency inventory, OSV/native-audit vulnerability data, registry deprecation metadata, and the chunk-similarity index, shelling out to `osv-scanner`, `gitleaks`, `jscpd`, and `knip` when they are on PATH and degrading gracefully (labelled fallbacks or `blocked_checks`) when they are not. Findings carry stable content-addressed `HL-` ids, split honestly into a "Proven" section (deterministic) and a "Needs judgment" section (ai-judged, confidence-scored), and never expose secret bytes — only a file:line + rule + fingerprint.

  Finding fingerprints use SHA-256 (a stable content-addressed dedup key, not a security primitive; secret bytes never reach it). All scanners are invoked from Node, so the workflow is cross-platform (Windows included). A baseline ratchet marks findings `new-since-baseline` vs `pre-existing` so a legacy project isn't drowned, `--offline` skips the network categories, and `paqad-ai health retest` re-runs the evidence and reclassifies each finding `fixed | still-open | needs-manual-verification` by its stable id. The workflow is classifier-routed (health phrasings route to codebase-health; pentest phrasings still route to pentest), surfaces in the dashboard, and its run summaries flow to the SIEM export.

## 1.57.0

### Minor Changes

- f76f2dd: Per-feature evidence report (issue #371): a feature's whole on-disk record — plan, frozen spec, every stage with real durations, the rules that ran, what retrieval found, the verification receipt, the AI-BOM, the commit trail, and the review — is now rendered into one self-contained, human-readable `report.html` by a pure script (no LLM, no network), saved next to the JSON it came from and byte-for-byte identical on every provider. A normal person can read it, it prints cleanly to PDF for an auditor, it stays local and git-ignored, and it makes zero external requests.

  Every section communicates gracefully when its data is absent: a missing plan, an unrun retrieval, or (on a non-enterprise install) an absent verification receipt and AI-BOM each render an explicit plain-English note instead of a blank gap. The verification receipt honestly says whether its hash-chain integrity recomputes, and a failed gate is shown as plainly and prominently as a passing one.

  New: `paqad-ai feature report [ref] [--out <file>] [--open] [--quiet]`. The report is regenerated automatically at end-of-change (covering Claude Code, Codex, and Gemini through the one verification backstop) and after every commit/merge (covering advisory hosts through the git hooks), always best-effort so it can never disrupt the feature-development stages or the verification verdict. Two config flags: `feature_report` (default on) and `feature_report_auto_open` (default off; sandbox-aware, skips CI/SSH/remote/headless).

  The page is laid out like a dashboard: a `▸ paqad` header, an at-a-glance overview of stat tiles (verdict, stages, duration, rules, retrieval, receipt, AI-BOM, delivery) with colored indicators, and a CSS-only submenu that drills into each section's detail — so the first glance is the summary and every detail is one click deeper, all still zero-JS and self-contained.

## 1.56.0

### Minor Changes

- 997bbc0: RAG retrieval was dark: local-model cosine scores on hybrid-fused results rarely reached the 0.75 precision floor, so every query fell back below-floor and the model never received a slice. Retrieval now uses floor-with-relief — the 0.75 floor still marks high-confidence hits, but when nothing clears it the top slices at or above a new `rag_relief_floor` (default 0.35, chosen from live probe data) are delivered tagged low-confidence instead of nothing. When retrieval still finds nothing, the session-context artifact carries one honest line naming the best score instead of silently omitting the section.

  Also wires the previously-defined-but-never-recorded `used` RAG-evidence event: the background context worker now records what it actually delivered into the artifact (injected sections, slice/pointer counts, top score, bytes) into the per-feature `.paqad/ledger/feature-evidence/<feature>/rag.jsonl`, so you can see whether RAG was used — not just that retrieval ran. Adds a `paqad-ai rag probe "<query>"` verb that prints pre-floor top-10 fused scores for diagnosis.

## 1.55.0

### Minor Changes

- adbf422: Add the code-knowledge index (issue #353): a deterministic, offline, zero-LLM map of every exported symbol (name, kind, file:line, signature, caller count, orphan flag) and the import/reference edges between files, persisted to `.paqad/indexes/code-knowledge.json`.

  - New CLI verb `paqad-ai index build` (scan → extract → edges → reachability → dependency usage → freshness header) and `paqad-ai index query <name|path>` (symbol/file card with signature, location, callers).
  - The index rebuilds incrementally on the existing detached context-refresh worker; a branch/commit change forces a full rebuild.
  - `index build` regenerates `docs/instructions/registries/reuse-catalog.md` and fills each module's `evidence.symbols` in the module map (comment-preserving).
  - Extracts the batched `git check-ignore` working-tree scan into one shared helper, reused by the rule-script runner.

  Built once, consumed twice: it powers dead-code findings (nothing imports this) and reuse answers (a helper already exists) for later issues.

## 1.54.1

### Patch Changes

- 11d36b2: Validate `stage end --artifact` paths at the boundary (#350). An absolute or out-of-tree artifact path was silently `join()`ed onto the project root, resolved to a non-existent in-repo file, hashed as "absent", and folded the stage to inconclusive — while the CLI still printed `{"recorded":true}` and exited 0. Now an in-tree path (absolute or relative) normalizes to project-relative and records normally, and a genuinely out-of-tree path is rejected loudly with a clear error and a non-zero exit. The `paqad:stage <stage> end -- <path>` marker gets the same treatment so chat-driven and shell-driven marks agree. The anti-spoofing "absent" semantics for a genuinely-missing in-tree file are unchanged.

## 1.54.0

### Minor Changes

- f3808cb: Routing: exclude `.paqad/` as well as `docs/` from feature-development. The bootstrap's routing narrative now tells the agent that a change confined entirely to the `docs/` and/or `.paqad/` directories is out of feature-development scope (no planning/spec stages), while a change touching any other directory is feature-development even when it also edits files under `docs/` or `.paqad/`. This matches the enforcement code in `src/stage-evidence/scope.ts`, which already excluded both paths; only the agent-facing narrative was under-describing the scope.

## 1.53.0

### Minor Changes

- 72f4222: Deliver the feature-development contract to the model and finish the per-feature evidence cutover (#345, #343).

  - **#345 G2/G3** — rule triggers are now scoped to path/glob-shaped inline code (fenced code blocks stripped), so a rule doc without an explicit `<!-- trigger: -->` no longer scoops up prose/code as triggers. This kills the `` `, ` `` manifest corruption and the whole-doc bloat/over-match (a representative repo artifact drops from ~128 KB to ~75 KB with zero manifest-region corruption). The manifest renders triggers as space-separated single backtick spans and strips backticks from the summary teaser; retrieval slices are deduped.
  - **#345 G4** — the rule-scripts checks verdict now says **⚪ none armed** at the completion seam instead of silently passing when no rule-scripts are registered.
  - **#345 G5** — the conservative decision-pause self-arm defaults **on within feature-development** (env/config can still force it either way) and never arms on any other route; a compact "decision pause is active" reminder rides with the feature-development rule slice.
  - **#345 G6** — a single exclusivity test proves every non-feature-development route loads no rules, runs no rule-scripts, and arms no decision pause.
  - **#343 A** — the frozen spec's only home is the feature bundle `specification.json` (the `.paqad/specs/*.frozen.json` sidecar and `frozen-spec-store.ts` are retired); the planning `<slug>.yaml` manifest relocates to `.paqad/planning/manifests`; the dashboard counts specs from the feature bundles; `.paqad/specs` and `.paqad/plans` are removed.
  - **#343 B** — per-feature `receipt.json` + `ai-bom.json` are projected from a feature's own graded rows (reusing the in-toto/DSSE/CycloneDX machinery), and the whole-project AI-BOM can be projected on demand from the union of feature bundles; per-feature writes honour the same enterprise gating as the whole-project receipt.

## 1.52.0

### Minor Changes

- c900ac0: Per-feature evidence bundle (#339): re-key the stage-evidence spine onto one
  git-ignored directory per feature. A change's plan/spec/stage evidence now live in
  `.paqad/ledger/feature-evidence/<issue>-<slug>-<ULID>/`, resolved from the active
  feature in the per-session control, instead of the anonymous `<session>/<ordinal>`
  scheme. The recorder, live-writer, finalize, verify, fold, narration, marker-parse,
  and the pre-mutation gate all key on the feature dir; new `paqad-ai stage start
--title/--issue` and `paqad-ai resume --feature <ref>` verbs open and reactivate named
  features. Storage location only — the row schema, hashing, and the stage spine's
  behaviour are unchanged.

## 1.51.0

### Minor Changes

- fd49d8b: Per-feature evidence bundle — Phase 1 foundation (dark) (#339).

  Lay the additive, unwired foundation for the "one git-linked directory per feature"
  model: each feature will get one directory
  `.paqad/ledger/feature-evidence/<issue>-<slug>-<ULID>/` holding its whole workflow
  record plus its compliance bundle. This phase ships the plumbing only — no behaviour
  change, so the live feature-development stage spine is untouched.

  - New `src/feature-evidence/` module: a path layer that resolves the per-feature
    directory, the `_session` control, and the `_chat` home and round-trips a dir name to
    its `{ issue, slug, ulid }` parts (reusing `deriveSlug` / `detectTicketRefs` / `ulid`).
  - Rigid, framework-owned AJV schemas for `feature.json` and `plan.json`
    (`additionalProperties: false`) with record builders that stamp a deterministic
    SHA-256 `content_hash`, so the stored bytes are script-owned rather than a
    free-written hallucination surface. `specification.json` reuses the existing
    `FeatureSpec` shape.
  - A per-session control (`_session/<sessionId>.json`) holding one active feature plus a
    paused-feature stack and the pending lane, folding today's `.open` + `.pending-lane`
    role at feature grain.
  - Path-agnostic session-ledger row primitives (`stampSessionRow` /
    `appendStampedRowToUnit` / `readUnitFile`) plus an additive feature-scoped
    stage-evidence ledger (`resolveActiveFeature` / `appendFeatureStageRow` /
    `foldFeature`) that reuses them and the stage-evidence fold core, so a change's stage
    rows can live at `<feature-dir>/stage-evidence.jsonl`. `appendSessionEvent` /
    `readSessionUnit` / `foldRows` / `foldChange` keep identical behaviour.

  Nothing writes to these paths yet; wiring the live recorder onto the feature ledger,
  plan/spec compile, git hooks, projections, and cutover follow in later phases of #339.

## 1.50.0

### Minor Changes

- bd42a6a: Route every prompt to one of 9 workflows first; load rules only for feature-development (#336).

  As its first action on every message, the agent now picks exactly one of 9 routing
  outcomes by intent (feature-development, project-question, documentation-update,
  module-documentation, pentest, design-test, rules-analyze, root-cause-analysis, or no
  workflow), narrates the pick, and only then loads what that outcome needs. Rules (text
  and scripts) and the lane load and run only for feature-development; the other real
  workflows use RAG when enabled but carry no rules, no lane, and no rule-scripts; "no
  workflow" loads nothing.

  - The framework bootstrap gains a route-first step and states the rules-only-for-feature-development load plus a per-message pause/resume rule (routing runs every message and never resets a paused change). No provider entry file changes.
  - A new `resolveRoutedWorkflow` normalizer folds the fine-grained classification into the 9 outcomes (a reroute layer — no classification union members are removed, so lane/budget/retrieval behaviour is preserved).
  - The prompt seam records the routed workflow in a per-session workflow-state (active plus a paused stack with resume anchors) and gates the lane to feature-development.
  - Rule-scripts run only on the feature-development route; the detached context worker composes the rule slice only for feature-development, seeds retrieval with the prompt, and retrieves nothing for "no workflow".

## 1.49.0

### Minor Changes

- 93bdd54: Stage-Spine 09 (#324): record and consume the lane — scale process depth to risk.

  paqad's deterministic classify→route→lane engine was fully built but never invoked
  in a live session, so every change (a one-line typo or an auth migration) paid the
  same full ceremony and the ledger's `lane` was always null. This wires the existing
  engine into the prompt seam and makes the lane real:

  - The prompt seam runs the deterministic classifier + router on the prompt text,
    stashes the chosen lane, and records it on the change's open ledger row (no LLM
    call added — path/prompt signals only).
  - The pre-code gate scales the specification requirement to the lane: the **fast**
    lane relaxes it (planning-only) while **graduated/full** keep the frozen-spec
    requirement. A null lane fails safe to full.
  - A new optional `sensitivity: high` per module in `module-map.yml` floors any change
    touching a sensitive path back to the full lane — a cheap, deterministic risk floor.
  - The completion backstop consumes the recorded lane instead of a hardcoded `'full'`,
    so a small change is no longer forced through the heaviest quality measurement set.

  Enforcement is tiered by host (hard-block on Claude Code; record-only on Codex/Gemini;
  prompt-followed on advisory hosts).

- 93bdd54: Stage-Spine 10 (#325): one end-of-change paqad receipt — surface the verdict, cut the noise.

  paqad's most valuable narration moment (the final verdict) had no reliable visible
  surface and didn't use the contract's own words, while the cheapest moments (per-stage
  boundaries) were spoken twice. This inverts the cadence:

  - The trust verdict now speaks the contract vocabulary — `Safe to merge` /
    `Needs your attention` / `Inconclusive` with the fixed status glyphs, led by the
    `▸ paqad` frame — consuming `paqad-voice.ts` (fulfilling its single-source claim).
  - A new end-of-change **receipt** composes the verdict headline with one line per stage,
    each carrying honest provenance: a stage that was only marked (no artifact, or a
    near-zero duration) reads 🟡 "marked (no recorded work)", never 🟢 "done".
  - The receipt is emitted as a visible `{systemMessage}` on the Claude completion hook
    (was buried on stdout); the git/CI backstop keeps plain text.
  - The duplicated per-marker END narration line is muted (the ledger write is unchanged —
    only the second spoken line is dropped).
  - The generated narration contract now states, per host, who narrates: Claude Code's
    hooks speak for you, but on Codex/Gemini the record hook is silent so the model must
    narrate its own markers — it no longer claims hook-driven ledger narration there.

- 93bdd54: Stage-Spine 11 (#326): truth tooling — `paqad-ai config effective` and a real `decision` CLI verb.

  Two small commands that make the framework honest and self-explaining:

  - **`paqad-ai config effective`** prints, per knob, the value that actually binds, the
    surface it came from (env → local `.paqad/.config` → tracked `configs/.config.*` →
    default), and the gate that consumes it. A knob shown `consumed by: NOTHING` is a
    placebo — a setting a team can change with no effect. The scan flags 12 verified
    placebos (the strictness/escalation/decision-threshold/research knobs). `rule_compliance`
    and `stages_mode` are shown through their real floored resolvers so the yaml-as-real-input
    truth (#319) is visible. Strictly read-only.
  - **`paqad-ai decision create|resolve|list`** is a real, install-resolved CLI verb for the
    Decision Pause Contract, replacing the `node runtime/base/skills/decision/scripts/*.mjs`
    path the contract named — which ENOENTs in a real onboarded project (the scripts only
    exist in the dev repo). It wraps the existing engine (`createPendingDecision` /
    `resolvePendingDecision` — same ULID mint, same packet format, no fork), validates the
    category with a nearest-match suggestion, supports `--other "<text>"` write-ins on
    resolve, and lists pending/resolved packets. The generated Decision Pause Contract now
    names `npx paqad-ai decision …`.

## 1.48.0

### Minor Changes

- 93e45d3: Stage-Spine 05 (#320): artifact-bearing stage markers — prove the work, not just the claim.

  A stage-end marker can now carry an artifact the recorder validates over its real
  on-disk bytes: `paqad:stage <stage> end -- <path>` (and `paqad-ai stage end <stage>
--artifact <path>`). The thinking stages — planning, specification, review — must
  reference a substantive (present, non-empty) artifact to count as complete. A bare
  marker pair, a missing file, or an empty file now folds to **inconclusive**, not
  complete, and no longer clears the pre-code gate. Mutation stages (development, checks,
  documentation_sync) are unchanged — the observed edit is their proof. Reuses the single
  `hashArtifacts` path (returns null when no real bytes exist) and preserves same-turn
  remediation (#307) and the docs/`.paqad` scope exclusion (#310).

- 93e45d3: Stage-Spine 06 (#321): per-change completion gate — stop later changes free-riding on the first.

  The end-of-change completeness gate no longer fires only once per session. On a passing
  verify, finalize now appends a `close` row and resets the session ledger's `.open` pointer
  (`closeSessionOrdinal`), so the next stage/edit opens a fresh ordinal and the pre-code gate
  re-arms — change #2+ earns its own verdict instead of inheriting change #1's markers. The
  verify-once early return is gone (each Stop re-verifies the open change; the last verify is
  the verdict), and the redo cap now counts only failed verifies since the last stage mutation,
  so re-verifying never spuriously trips it while a stuck change still marches to `blocked`
  (#303 bite-once preserved). Docs-only / `.paqad`-only changes still no-op (#310).

- 93e45d3: Stage-Spine 07 (#322): deterministic ticket intake — make "do PQD-123" fetch the real ticket.

  Wires the front door of the ticket → PR loop so the spec grounds in the actual ticket text
  instead of a guess from the id:

  - **`paqad-ai intake fetch <ref>`** — GitHub issues via `gh issue view` (mapped through a new
    `GithubIssuesTicketProvider`), Jira via the Atlassian MCP in-session; prints the normalized
    ticket and records an optional `ticket_intake` stage row. Graceful when `gh` is absent or the
    ref is unrecognised; intake is a bookend and never blocks a change.
  - **Prompt-seam detector** (`detectTicketRefs`) + a Claude-Code `UserPromptSubmit` arming hook:
    a ticket ref in a prompt surfaces a `▸ paqad` line pointing at `intake fetch`. Advisory on
    hosts without the seam.
  - Adds an optional "Stage 0 — ticket_intake" to the feature-development rule and fixes the
    `conventions.intake_decisions` → `process.intake_decisions` key mismatch in the policy text.

- 93e45d3: Stage-Spine 08 (#323): ship `paqad-ai deliver` — wire the dead delivery engine and close the CI loop.

  The ~1,900-line delivery engine (branch/commit/PR + CI wait-for-green + on-red-stop + evidence
  comment) had no invocation path. `paqad-ai deliver` now runs the tested chain end-to-end:

  - `--dry-run` renders the branch/commit/PR text without pushing.
  - The real path asks first via a mandatory `delivery.open_pr` Decision Packet (opening a PR is
    outward-facing and hard to reverse), then runs `renderDelivery → runDelivery → runCiGate`,
    waits for CI (`wait_for_green` / `on_red: stop`), stops with a clear reason on red (never a
    false success), and posts the rendered verification evidence to the PR on green.
  - Reuses `src/delivery/*` — no hand-rolled git/gh flow.

  Also fixes the delivery-policy evidence instruction that promised an auto-posted comment that
  never happened: it now names `paqad-ai deliver` (auto-posts on green) plus the manual
  `paqad-ai evidence --output … && gh pr comment --body-file …` fallback.

  Deferred (follow-ups): a Bash `PreToolUse` deny of hand-rolled `gh pr create` / `git push` while
  a `delivery.open_pr` packet is pending (the pause is already enforced by the verb), and adding a
  delivery block to this repo's `feature-development.yaml` + having `paqad-ai update` append missing
  default blocks (ties to #12).

## 1.47.0

### Minor Changes

- 49db0e3: Make the session-context rule contract fail-safe (#316). `writeRuleContext` could
  write a drift-, memory-, or retrieval-only artifact with zero rules when the compiled
  rules store was absent or empty. Because the framework bootstrap only loads the full
  `docs/instructions/rules/` tree when the artifact is _missing_, a rules-less file was
  silently treated as the rule contract and every project rule vanished from context.
  The writer now prepends an explicit fallback marker to any written artifact that
  carries no rule manifest, so a bootstrap-obedient agent always knows to load the rules
  in full. A populated store is unchanged (byte-identical).
- 49db0e3: Ship `paqad-ai spec freeze` and activate the built-but-dead spec sign-off engine
  (#317). The `src/spec/` freeze machinery (build → evaluate → freeze → write frozen
  sidecar) was fully implemented and tested but had no caller and no instruction naming
  it, so the "spec frozen and signed off before code" promise was enforced by nothing.
  The new `spec freeze <spec-file>` verb wires the existing engine end to end: it prints
  every freeze blocker and exits non-zero (nothing written) when the spec is not
  freezable, and on a clean spec writes the frozen sidecar at `.paqad/specs/<id>.frozen.json`.
  The specification-stage instructions and the feature-development rule now name the
  command so the agent runs it. No freeze logic is reimplemented.
- 49db0e3: Build the deterministic check runner and stop assuming tests passed (#318). The
  `checks` stage is meant to be 100% deterministic — run format/test/build and block
  on red — but nothing executed the commands: the resolver had no caller and the
  completion backstop hardcoded `code_tests_lint_passed: true`, so a change with
  failing tests could still be reported green by the framework layer.

  New `paqad-ai checks run` verb resolves the project's mapped commands, executes
  them, and persists one `StructuredTestResult` per command (the shape the
  `code-tests-lint` gate already consumes) to `.paqad/checks/last-run.json`; it exits
  non-zero on any red. The completion backstop now reads that report: it populates
  `structured_test_results`, derives `code_tests_lint_passed` from real execution (no
  longer a hardcoded `true`), and replaces the `code-tests-lint` gate's skipped
  placeholder with the report-driven verdict — a red report blocks the completion
  verdict, a green one passes, and an absent report reads as Inconclusive rather than
  a vacuous green. Deterministic throughout: a command's exit code is the verdict.

- 49db0e3: Arm the rule-scripts gate by generating the rule-script map at onboarding (#319).
  paqad's deterministic, no-LLM rule enforcement engine was live but disarmed on every
  fresh project: `rule-script-map.yml` — the map linking rules to their compiled
  scripts — was produced by no code path, so the enforcement seam fast-skipped on the
  missing map and the gate passed by default. And the strictness a team set in
  `feature-development.yaml` (`checks.rule_compliance.mode`) was read from a different
  surface at runtime (`.config`, default `warn`), so a team asking for `strict` silently
  got `warn`.

  New `paqad-ai rules compile` verb (and `compileRuleScripts`) generates the map from
  the rule tree — embedding stable rule ids and listing every rule via the existing
  analyzer + atomic-writer, carrying over any bound scripts — and the onboarding
  orchestrator now runs it after the rule refresh, so a fresh project is armed. The
  strictness resolver now folds the project's on-disk `feature-development.yaml`
  `rule_compliance.mode` as a real, team-tracked floor (stricter of it and `.config`
  wins; local/env may only raise), and the policy merge no longer silently drops
  `rule_compliance` when a project supplies its own workflow file. No enforcement or
  atomic-apply logic is reimplemented.

## 1.46.2

### Patch Changes

- b3fc7df: fix(#313): cross-provider enforcement + RAG coverage from the dogfood benchmark

  - **Codex stage markers no longer lost.** On `codex-cli` the completion `Stop`
    payload carries no readable `transcript_path` and its inline final message is
    marker-less, so well-behaved Codex runs recorded zero stages and were silently
    scored "blocked". The record-only hook now reads the session's own
    `~/.codex/sessions/**/rollout-*.jsonl` (honoring `CODEX_HOME`), and the marker
    parser now understands Codex's `payload`-nested rollout shape.
  - **`module-docs-structure` stops over-blocking pre-existing flat docs.** A
    doc-sync that merely touched a flat `docs/modules/{module}/features/{feature}.md`
    file already established repo-wide is no longer hard-failed into a revert (same
    family as #310). A lone flat doc introduced into an otherwise-nested repo still
    fails.
  - **Honest RAG host-surface coverage.** Documented that the `UserPromptSubmit`
    retrieval seam only runs where the host executes that hook; the JetBrains Claude
    surface did not in the benchmark, so retrieval degrades to grep/read there.

## 1.46.1

### Patch Changes

- c0e7efa: Fix #310: the feature-development stage gate blocked documentation-only work and could deadlock unclearably.

  - **Scope.** The pre-mutation and completion stage gates now govern **feature development only**. A documentation-only change (`docs/**`, markdown) or a framework-internal change (`.paqad/**`) is no longer forced through the planning → specification → … → checks stages. The check is language-agnostic (an exclude list, not a `src/` allowlist), so it holds for any onboarded stack (Laravel `app/*.php`, Python, Go, …), and it keeps full teeth on real source edits.
  - **No deadlock.** The live writer no longer stamps a stage (e.g. `development`/`documentation_sync`) before the pre-code stages are recorded — that phantom used to poison stage ordering so `planning` could never be recorded again. The recorder no longer rejects an out-of-order earlier `stage_start`; ordering is judged non-destructively by the completion fold, so the stages the gate demands can always be recorded and the same-turn marker remediation actually clears the block.
  - **Consistent predicate.** An `end` with no matching `start` is now `inconclusive`, not silently `complete`, so the pre-mutation gate and the completion verifier agree a stage needs a start.
  - **Reachable remedy.** Editing `.paqad/configs/.config.policy` (the `stages_mode` escape hatch) is no longer blocked by the gate it configures.

## 1.46.0

### Minor Changes

- 944f52f: Stages gate: same-turn unblock that actually works, sentinel bootstrap un-deadlocked, and stage narration everywhere (#307).

  - `paqad:stage` markers are now parsed at the pre-mutation seam too, so markers emitted earlier in the same turn clear the block-forward gate immediately — not only after Stop.
  - New `paqad-ai stage <start|end> <stage>` CLI verb replaces the never-shipped `scripts/se-mark.ts` as the shell escape hatch; the block message, framework bootstrap, and decision-skill docs now name only remediations that exist on an onboarded project.
  - The write of `.paqad/.agent-entry-loaded` is exempt from both the agent-entry gate and the stages gate: turn one can complete the bootstrap it is being asked to perform.
  - Narration and ledger are both non-negotiable: every stage-evidence row minted from markers (pre-mutation sweep, Stop parse, CLI) is narrated back to the developer as a `▸ paqad` line via the host's user-message channel; allow-path advisories use `systemMessage` instead of invisible stdout.
  - Guardrails: a packaging-truth test suite pins that every runnable path/verb named in user-facing remediation surfaces resolves in the published package, and `src/stage-evidence/**` now holds a 100% coverage floor (statements, branches, functions, lines).
  - Completion-backstop over-block fixed (decision `D-01KWYDTDZ24CV802R2HGDS4RH4`), removing two false blocks that hit every onboarded repo's first code change: (1) an implementation-drift canonical doc that does not exist on disk is no longer treated as an unresolved obligation — a code change cannot stale a framework-assumed doc (`docs/maintainers/architecture-map.md`, `docs/modules/README.md`) the project never created; existing drift docs are still flagged and required per-module docs stay enforced; (2) test-evidence strength is a provider-workflow concern the agent-independent backstop cannot collect, so at backstop origins it now escalates (visibly) instead of hard-blocking — in-session and CI still enforce it.

## 1.45.0

### Minor Changes

- b07dc02: Decision Pause now mints packets on more of the forks that matter (#300, option B2):

  - **Self-arm broadened to architecture-path.** Alongside create-vs-reuse (0.92), the opt-in self-arm minter now also arms on a new tight `explicit-path-fork` detector signal (0.90) — two distinct file paths offered as alternatives ("live in X or Y", "X vs Y"). The pre-existing broad architecture-path signals (a bare "or", two paths merely mentioned) stay at 0.64 and never clear the arming bar, so a stray "or" cannot mint a pause. Self-arm remains OFF by default.
  - **spec.change now has a deterministic minter.** A new always-on, no-opt-in spec-change guard runs at the pre-mutation seam: when a persisted frozen spec's source markdown has moved since freeze (`isFrozenSpecStale`), it mints one `spec.change` pause via `buildSpecChangePacket`. It is naturally inert until a spec is frozen and its sidecar persisted (`writeFrozenSpec`), so nothing changes for projects that do not use the spec-freeze lifecycle. Both minters only write a pending packet; the existing decision-pause gate still owns the block on the next edit.

  Cross-provider: the architecture-path leg inherits self-arm's existing transcript-based provider coverage (parity with `HOOK_COVERAGE_MATRIX`); the spec-change guard is provider-independent (it reads spec files on disk, not the turn transcript).

  Also fixes `buildSpecChangePacket` copy that could never pass `lintDecisionCopy` (banned word "invariant", non-approved label verb, em dashes), which had silently blocked the packet from ever being written to the pending store.

## 1.44.1

### Patch Changes

- 91e4798: Fix the Claude Stop hook so it respects the paqad enable/disable flag and can no longer wedge a session in an infinite loop.

  - **Respects ON/OFF from the real project root.** `verification-completion.mjs` now resolves the project root via `CLAUDE_PROJECT_DIR` / `PAQAD_PROJECT_ROOT` (cwd fallback) like the sibling Stop hooks, instead of raw `process.cwd()`. A project set to `paqad_enable=false` is honored even when the host launched the hook from a subdirectory (previously the disable flag was missed and the OFF project was still blocked).
  - **Bites once, never loops.** Every blocking Stop hook now reads Claude's `stop_hook_active`: the gate still blocks (exit 2) on the first stop so the model gets a turn to fix it, but once it is already inside a Stop-hook continuation it steps aside (surfaces the summary, exits 0). An unresolvable verdict can no longer drive an infinite Stop loop. The git/CI backstop remains the hard, non-bypassable layer.

## 1.44.0

### Minor Changes

- 92c5d52: Decision Pause: default `decisions_ask_threshold` to `strict` (humans decide; the machine does not auto-resolve mid-confidence packets).

  Previously the default was `balanced` (0.85), which let the resolver auto-resolve any decision packet whose recommendation cleared 0.85 confidence. The default is now `strict` (0.95): packets in the 0.85–0.94 confidence band surface to a human instead of resolving silently. Projects that never set the key resolve to `strict`, and fresh `paqad-ai onboard` writes `ask_threshold: strict`.

  This is a behaviour change on update. Teams that prefer auto-resolution can opt back in by setting `decisions_ask_threshold=balanced` (or `permissive`) in `.paqad/configs/.config.policy` / local `.config`, or via the `PAQAD_DECISIONS_ASK_THRESHOLD` env var. Applies uniformly across all providers (core/config, not entry-file behaviour).

## 1.43.0

### Minor Changes

- 3bc15df: Publish two measured, reproducible benchmark numbers with methodology and caveats
  (issue #285). Adds read-only repo tooling: `scripts/measure-footprint.mjs` reports the
  resident session-start token footprint per area (real tokenizer via
  `src/context/tokenizer-cache.ts`, labelled char/4 fallback), and
  `scripts/rule-findings-stats.mjs` reads the existing `rule-evidence` ledger via
  `readProjectEvents` and buckets deterministic findings by ISO week. Results, method, run
  counts, tokenizer version, per-tier applicability, and caveats live in
  `docs/instructions/benchmarks/measured.md`. The two unbenchmarked "60-85%" README claims
  are replaced with the measured 49-61% resident-load reduction and a link to the method.
  No product behavior changes; `rag_enabled` stays default off.

## 1.42.0

### Minor Changes

- 561665d: Token-neutral by default: lean rule loading is now the default delivery path (issue #284).

  A new `lean_rules` flag (default **on**, env `PAQAD_LEAN_RULES`) makes the always-resident rule manifest plus trigger-loaded applicable rule text the default, instead of loading the whole `docs/instructions/rules` tree every session. The framework bootstrap and the Claude Code prompt-gate now read `.paqad/context/session-context.md` artifact-first, falling back to the full rule load only when the artifact is missing. On Claude Code the session-time seam and the background refresh trigger are ungated from `rag_enabled` so the rule slice is injected and kept current with no embedding, index, or provider call on the lean path; `rag_enabled` continues to govern only what retrieval/memory/drift sections compose into the same artifact. A committed resident-footprint budget test and a `paqad-ai doctor` readout gate the token cost. `lean_rules=false` restores the previous full-load behaviour exactly, and paqad-disabled stays a pure no-op.

## 1.41.1

### Patch Changes

- 2137219: Rule-script whole-tree scan now respects `.gitignore`. Previously the scanner
  enumerated the working tree with a fixed ignore list (`node_modules`, `dist`,
  `.paqad`, `build`) and never consulted the project's `.gitignore`, so gitignored
  build output, vendored dependencies, and generated code were still scanned —
  producing `deterministic` findings on files the developer cannot hand-fix and
  blocking the strict `rule_compliance` gate. The scan now drops git-ignored paths
  via a batched `git check-ignore` (falling back to the static list when git is
  unavailable), and adds `vendor/` to that fallback list.

## 1.41.0

### Minor Changes

- 7d3bed0: Analytics v2 (#279): turn analytics instrumentation into a tracking-plan-as-code.

  When `analytics_instrumentation` is on, paqad now makes the per-event docs tree the single
  source of truth for what a project tracks, and governs every event through the normal PR:

  - The #241 `paqad.analytics-tag` ledger is removed (redundant with the docs); the flag,
    detection, classify-time gate, and conflict decision-pause categories stay.
  - A `docs/instructions/stack/analytics.md` tracking-plan doc is generated from provider
    detection (OFF stays silent).
  - Framework analytics rules are compile-time gated on the flag (`<!--gate:-->` frontmatter),
    so zero analytics bytes reach the model when off.
  - A per-event docs tree `docs/modules/{module}/analytics/{feature}/{event}.md` (one doc per
    event, a section per provider, normalized-slug filenames that collapse casing variants) is
    generated by the documentation workflow and the doc-sync stage.
  - Every new event opens an `analytics.new_event` Decision Pause packet (who/why), and the
    feature-development stages inject analytics instructions when the gate resolves to instrument.
  - One `AC-TRACK` per event flows through spec freeze and traceability (an unproven event is a
    `TR-UNTESTED-PROMISE`), gated by doc existence with a new `analytics_strictness` knob
    (off | warn | strict, default warn).
  - A new `analytics-instrumentation` skill writes the doc + emits the provider snippet.

## 1.40.0

### Minor Changes

- 30534cf: Add the complementary analytics-instrumentation agent (#241): an opt-in, coding-first,
  provider-detected capability that wires a feature's analytics tracking on top of a correct
  build. Ships the `analytics_instrumentation` flag (default off), read-only provider +
  convention detection, a classify-time gate carried forward via a sidecar, analytics conflict
  categories on the Decision Pause Contract, and a new script-written `paqad.analytics-tag`
  ledger on the shared session-ledger substrate — flag-gated recording, script-driven reading
  (`paqad-ai analytics show`), the generated `analytics-tracking-map.md` registry
  (`analytics map`), cross-provider record seams (Claude PreToolUse + Codex/Gemini completion
  markers), and SIEM export inclusion.

## 1.39.0

### Minor Changes

- 7d48ba0: Ship a `decision` skill that authors Decision Pause packets — mint collision-free `D-<ULID>` ids, drive the pending → resolved lifecycle, and commit resolved packets with the PR (issue #272).

  The Decision Pause Contract asks the agent to write a packet to `.paqad/decisions/pending/D-{id}.json`, present it, then move it to `resolved/` with `chosen` / `rationale` / `resolved_at`. But nothing minted the id or wrote the JSON, so an agent hand-authored the packet and pattern-matched the legacy numeric `D-1` / `D-2` / `D-3` fixtures into a sequential `D-4` — the exact id-collision the `D-<ULID>` form from #184 exists to prevent. This is the writer the contract lacked, the counterpart to `scripts/se-mark.ts` on the stage-evidence ledger.

  - **New `src/decisions/authoring.ts`** (re-exported from the root `paqad-ai` barrel): `createPendingDecision` mints a `D-<ULID>` id, validates the content, and atomically writes the pending packet; `resolvePendingDecision` records the chosen option and rationale, moves the packet to `resolved/`, and stamps `resolved_at`. Both reject a non-ULID id, so a hand-picked sequential `D-{N}` can never be minted — the guarantee is enforced at creation time, not by scanning the repo.
  - **New bundled `decision` skill** (`runtime/base/skills/decision/`): thin `create.mjs` / `resolve.mjs` wrappers so the agent supplies only content, never the id, timestamps, or JSON plumbing.
  - **The Decision Pause Contract** (in `AGENT-BOOTSTRAP.md`) now points at the skill's create/resolve scripts, and the **delivery workflow** (`delivery-policy.yaml`) documents that a resolved decision packet is committed with the change it justifies, so a reviewer and future `git blame` can see why.

## 1.38.0

### Minor Changes

- 46e8d7a: Make the mandatory `review` stage recordable when review happens after tests/docs (issue #270).

  The stage-evidence ledger enforces a canonical stage order (`planning → specification → development → review → checks → documentation_sync`) and rejects an earlier stage that starts after a later one, so the recorded order can't be faked. `review` is the one stage this punished unfairly: it is **edit-less** (a review of the finished diff mutates no file, so the live writer can never stamp it) yet canonically **precedes** `checks` and `documentation_sync` — the stages the live writer _does_ stamp from the tests and docs written during the build. An honest review of the completed change therefore lands, in wall-clock time, after those rows already exist, and the completeness gate reported it as `incomplete — missing [review]`, indistinguishable from a skipped review.

  - **`review` is now a completion-anchored stage** (`COMPLETION_ANCHORED_STAGES` in `src/stage-evidence/stages.ts`): its canonical position is the completion boundary, so it is exempt from forward-ordering. The recorder no longer treats a completion-anchored start as out-of-order, the fold flags no ordering violation for a pair involving one, and the finalize seam already anchors an open review at the completion clock.
  - **Honesty floor unchanged.** The exemption forgives ordering only, never absence: a review that is never marked is still `missing` → `incomplete`, so "reviewed late" stays distinct from "not reviewed". Rows remain script-minted, and the exemption is scoped to `review` alone — a genuine overlap between two non-anchored stages still flags.
  - `docs/verification-enforcement.md` documents the completion-anchored ordering contract.

## 1.37.0

### Minor Changes

- 0d8b0db: Extend the enforcement record tier from Claude-only to Codex and Gemini, and document the honest cross-provider tier ladder (issue #265).

  The stage writer and pre-edit block are Claude-only by physics (only Claude Code exposes a pre-mutation hook). But the _ledger_ half of the fix is portable to any host with a completion hook, so it now binds on Codex and Gemini too:

  - **Codex / Gemini record their `paqad:stage` markers at turn end.** The record-only completion hook (`verification-record.mjs`, wired on Codex `Stop` and Gemini `AfterAgent`) now parses the agent's stage markers from the turn transcript and writes them to the same stage-evidence ledger the completion verify folds. Each row is attributed to the host that ran (`codex-cli` / `gemini-cli`), passed to the hook as an argv — never mislabelled `claude-code`. Codex reads its `transcript_path`; Gemini falls back to the inline `prompt_response` because its `transcript_path` is currently stubbed empty upstream ([google-gemini/gemini-cli#14715](https://github.com/google-gemini/gemini-cli/issues/14715)). The parser degrades gracefully to a raw-text scan when a transcript format is not the Claude JSONL shape.
  - **Record-only, by design.** These hooks still always exit 0 and stay silent — there is **no in-chat verdict** on Codex/Gemini, because Codex rejects plain text on `Stop` and Gemini forces a retry on `decision: deny`, so the only non-disruptive channel is the ledger. The verdict is visible via the dashboard / SIEM export, never shoved into the chat.
  - **No pre-edit block, stated plainly.** Codex/Gemini have no pre-mutation seam, so the hard block stays Claude-only. `docs/verification-enforcement.md` now carries a cross-provider guarantee table (hard block + verdict = Claude; record + ledger = Codex/Gemini; advisory = the 8 remaining hosts) and tracks the non-Claude hard block as a known, physics-bounded, upstream-blocked limitation.
  - **The mandate holds:** enforcement is never added through an entry-file, prompt, or template edit. A parity test asserts the stage-writer and pre-mutation deny hooks are present for `claude-code` and absent for `codex-cli` / `gemini-cli` and every advisory host.

## 1.36.0

### Minor Changes

- 69ab154: Add a native `aiassistant` adapter for JetBrains AI Assistant (#219).

  - Onboarding and `paqad-ai refresh --providers` now generate and keep in sync `.aiassistant/rules/guidelines.md`, the lean bootstrap-pointer entry file AI Assistant auto-applies from `.aiassistant/rules/`.
  - Soft, rules-only adapter (advisory hook coverage), like `junie`: AI Assistant exposes no hook/lifecycle system, so the sentinel gate cannot bind. MCP is intentionally omitted — AI Assistant configures MCP servers in the IDE, not a project file, so no dead artifact is written.
  - The adapter is selectable everywhere the other ten are (onboarding prompt, `--providers`, factory), carries its Decision Pause Contract UI note, and is covered by tests parallel to `junie`.
  - Also synced the `onboarding-manifest` schema `adapter` enum to the full adapter list (it had silently drifted to five, so a `cursor`/`aider`-onboarded manifest failed health-check validation).

- 69ab154: Make the feature-development stage workflow **compel, not plead** (enforcement RCA, part 1 of the fix).

  The stage-evidence recorder finally has a production caller, and a code edit is now blocked until the prior stages are recorded — closing the physics gaps that let every prior fix (#117–#261) regress.

  - **Deterministic per-stage writer.** A new Claude PreToolUse hook (`stage-writer.mjs` → `src/stage-evidence/live-writer.ts`) script-mints a `live-mark` stage row on every Edit/Write/NotebookEdit, with real start/end times classified from the mutated file — no model involvement. The completion finalizer closes any stage left open at the turn boundary.
  - **Block-forward deny.** A `stages` capability folded into the kernel evaluates at the pre-mutation seam and refuses an edit (exit 2, reason on stderr) until `planning` and `specification` each carry a recorded start+end pair. It reads the ledger, not a git delta, so a committed clean tree cannot bypass it. `se-mark` (a Bash script, ungated) is the escape hatch that clears the block.
  - **Visible, non-vacuous verdict.** The Stop backstop now writes a failing verdict to **stderr** (the host surfaces only stderr to the model on exit 2), and the stage gate no longer skips on a zero-file working-tree diff — a committed-but-incomplete change still fails instead of passing silently.

  Claude-only for the hard block (the only host with a pre-mutation seam); Codex/Gemini keep completion-time recording; other adapters are unchanged. Default `stages_mode` is strict.

- 69ab154: Wire the last three enforcement consumers so the framework is felt, not just recorded (enforcement RCA, part 2 of the fix).

  Building on the stage writer and block-forward deny, three contracts that shipped with a policy but no live consumer now bind through the kernel:

  - **Delivery policy is enforced.** A `delivery` capability at the completion (Stop) seam reads HEAD branch/commit and — when `gh` can answer — the PR/CI state, then **warns** on a convention deviation (on the base branch, an off-convention branch name, red CI under `wait_for_green`) and appends a `delivery-evidence` row. Warn-floor by design: delivery is `mandatory:false`, so it surfaces a bad push one turn late but never blocks. Degrades cleanly when `gh` is absent.
  - **The stage is printed on entry.** The stage-writer PreToolUse hook now prints a plain-English `▸ paqad · <stage>` line (via Claude's user-visible `systemMessage` channel) the first time a change enters each stage, so the developer sees the workflow running even when the model forgets to say it. Claude-only (the sole pre-mutation host); idempotent per change.
  - **The Decision Pause Contract self-arms.** An opt-in pre-mutation capability reads the recent prompt from the turn transcript and, on a high-confidence create-vs-reuse fork with no decision pending or already made, mints ONE pending decision packet so the existing decision-pause gate blocks the _next_ edit — closing the "nothing mints the packet" gap. **Off by default** (enable with `PAQAD_DECISION_SELFARM` or a local `.config` `decision_selfarm` line); it only mints, never blocks, so the current edit is never interrupted.

  The kernel gate now threads an optional tool/turn payload (edit target, transcript path, session id) to each capability; every existing capability ignores it. Coverage stays at the 95% branch gate.

## 1.35.0

### Minor Changes

- fa171f3: Capability Kernel (F1–F8): unify the five enforcement contracts under one framework-owned, versioned kernel.

  - Stage-evidence, rule-scripts, decision-pause, delivery, and narration are now rows in one `CapabilityRegistry`, each with per-capability policy/record schema versions.
  - Evidence consumers (the dashboard and `paqad-ai audit export` / SIEM) read the always-on #249 session-ledger; the delivery, rule-compliance, and decision stores fold onto it via a shared project-ledger helper (dual-sink — the operational files the engine needs are preserved, so they stay in lockstep).
  - `audit export` now unions the session-ledger doc types into the OCSF/ECS/CEF fold-view as a new `session` event kind, graded for a SOC.
  - Compat spine (D2): the bless stamps a per-capability version vector into `capability-lock.json`; an install older than the schema a project was blessed under refuses to enforce cleanly (non-blocking) rather than misread a newer format.
  - Removed the dead LaneRunner/SliceExecutor orchestration engine, its 19 pipeline phases, and the `paqad-ai plan resume` CLI command (they backed the trigger-independent engine that never ran at session time).

## 1.34.0

### Minor Changes

- ab9db21: Stage-evidence enforcement: a deterministic gate that fails a code change whose feature-development workflow was left incomplete.

  `runRepositoryVerification` now folds the stage-evidence ledger into a `stage-evidence` verification gate, read from the ledger files on disk (never an LLM claim). It is code-change-only and scoped so it cannot break a project that has not adopted stage marking:

  - Every mandatory stage recorded (`complete`/`recovered`) → pass.
  - The workflow was started but left incomplete (the agent live-marked at least one stage, a mandatory stage is missing) at a local origin (`hook-completion`/`git-backstop`) → **fail**, which flips the trust verdict so the git backstop blocks the commit.
  - Never marked, or running on CI (a fresh checkout has no committed local ledger) → skipped/informational. The committed-receipt path that would let CI enforce stage-completeness is deferred.

  Adds `live_marked` to the stage-evidence verify result (distinguishing "started the workflow but left it incomplete" from "never marked anything"), a `scripts/se-mark.ts` helper to drive the recorder from the shell, and updates `docs/verification-enforcement.md`.

## 1.33.0

### Minor Changes

- da75225: Cross-platform hooks, always-load entry gate, and two new evidence ledgers.

  - **Always-load entry gate (#240 / Part 0):** the UserPromptSubmit gate now emits the framework-load directive first and suppresses the precomputed context block until the framework is loaded, so the "load first" instruction can never be buried. The four blocking gate hooks are ported from POSIX-only `.sh` to cross-platform `.mjs` and wired as `node "<abs>/hooks/<file>.mjs"` — no bare `~`, no `.sh`, no shebang reliance — so onboarded projects work on Windows. The per-machine host hook configs are git-ignored via a nested `.gitignore`; legacy commands are pruned on re-onboard.
  - **Stage-evidence ledger (#247):** a script-written, per-code-change JSONL record proving each mandatory feature-development stage ran, in order, with a start/end datetime per stage and a derived duration, plus an end-of-change completeness gate that fires automatically at completion (verifying tracked changes, or writing an honest inferred-git backstop record for an untracked diff). Always-on and independent of the enterprise/AI-BOM flags.
  - **Decision-reuse ledger:** every reuse of an already-approved decision from `.paqad/decisions/resolved/` is recorded to a git-ignored, session-scoped ledger (one record per reuse). Built on the same shared session-ledger substrate as the stage-evidence and RAG-evidence ledgers.
  - Removes the redundant "Use this file as the repository entrypoint…" line from every agent entry-file template.

## 1.32.0

### Minor Changes

- 7812cb8: Activate the feature-development workflow so an LLM actually runs it. Adds `feature-development.md` as a canonical coding-capability rule (mirroring `pentest.md`/`design-test.md`): on any intent to create or change code, the agent must run the feature-development workflow's stages in order — planning, specification, development, review, checks, documentation_sync — honoring each stage's flags and escalations via the Decision Pause Contract, and following `delivery-policy.yaml` on delivery. Previously the stages were declarative YAML that nothing told the agent to execute, so the workflow was never followed on the prompt path (the only seam common to every provider). Every stage is mandatory; the lane sets depth, never omission. A regression guard asserts the rule ships, mirrors into the contract, and keeps every mandatory stage and the do-not-improvise framing.
- 08ee215: Add the RAG-evidence ledger and harden the release workflow (issue #249).

  - **Release fix:** `changeset version` no longer hard-fails on a transient GitHub GraphQL flake. A resilient changelog adapter keeps the rich GitHub changelog when the API is healthy and falls back to a git-style line on any error.
  - **Session-ledger substrate (#249 P0):** a reusable, script-written, session-scoped append-only JSONL primitive (atomic ordinal allocation, `.open` pointer, script-clock `ts` + identity `content_hash`, tolerant reader, injectable validator) under `.paqad/ledger/`, consumable by the stage-evidence ledger (#247) too. Imports no enterprise code (always-on, AI-BOM-independent).
  - **RAG-evidence ledger (#249 P1–P3):** a per-(session, conversation) record of what RAG actually did — `refreshed` / `called` / `used` / `fallback` — recorded from the real seams (background worker + prompt hook); `appendRagAudit` dual-writes into the structured ledger so it is the queryable source of truth with no event lost. AJV-validated, script-only (the LLM never hand-authors a row). `paqad-ai rag-evidence show` folds a session into a use-rate / fallback rollup. Honest by design: proof of occurrence, never of benefit.

- 5d742f0: Wire paqad's built-but-unused RAG + smart-rule machinery into live sessions as an optional, eval-gated accelerator on top of the grep/agentic default — never blocking, token-saving, deterministic-first, and honest (27 features, F1–F27).

  - **Non-blocking spine (F1–F3):** a detached background-worker harness (atomic swap, single-flight lock, debounce) and a `UserPromptSubmit` seam that injects a precomputed context artifact under a hard time budget. Disabled / cold-start / `rag_enabled=false` emits nothing — byte-identical to today's behavior.
  - **Smart rule loading (F4–F6):** an always-resident rule manifest plus deterministic trigger-loaded full rule text (no embeddings for rules), and live `PreToolUse`/`Stop` rule-script enforcement so lazy rule text stays safe.
  - **Branch-aware index substrate (F7–F10):** branch/commit/base metadata, a content-addressed embedding cache (idempotent re-embeds, zero-cost branch switch-back), background incremental working-tree sync, and a `rag_base_branch` config knob.
  - **Retrieval wired into sessions (F11–F14):** top-k slices injected on the seam, a precision floor with live-file-verify framing, docs/module-map-first scope, and stage-aware gating.
  - **Prove + honest (F15–F16):** an on/off A/B eval gate (hit@k, task-success, prompt-tokens) that blocks regressions, and README/docs copy corrected to match what actually ships.
  - **Code retrieval + precision (F17–F19):** hybrid BM25 + RRF fusion, an opt-in reranker, and stage-routed function-level code slices — all safe-by-construction and eval-gated.
  - **Higher structure (F20–F21):** an embedding-free structural repo-map (import-graph PageRank skeleton) and a deterministic cross-session codebase-memory tier (supersede-by-key, token-budgeted).
  - **Polish (F22–F27):** cAST split-then-merge chunking with a chunker-versioned index (clean rebuild on strategy change), an opt-in code-tuned local embedding model (MiniLM stays the default floor), deterministic contextual blurbs before embed + BM25, decision-precedent enrichment on the decision pause, a distilling context pack (path:line pointers, not dumps) for long workflows, and proactive base-drift awareness (debounced off-path `origin/<base>` heads-up).

  All retrieval/precision changes are gated by the F15 eval; retrieval stays off until `rag_enabled` is set, and every path falls back cleanly to grep when disabled, cold, or below the similarity floor.

### Patch Changes

- d6a5495: Have paqad announce each feature-development stage as it runs it. The feature-development workflow rule now instructs the agent to emit one compact `▸ paqad` status line, in the existing narration-contract voice, as it enters each stage (planning, specification, development, review, checks, documentation_sync, delivery). This makes the workflow visible to the developer and gives a live, stage-by-stage signal that the workflow is actually being followed.

## 1.31.0

### Minor Changes

- [#243](https://github.com/Eliyce/paqad-ai/pull/243) [`4f30a09`](https://github.com/Eliyce/paqad-ai/commit/4f30a09f0713822a303c5ebfdb88fe995491fb24) Thanks [@HLasani](https://github.com/HLasani)! - Load the workflow policies as part of the canonical project contract. The framework bootstrap and the agent-entry hooks now instruct the agent to load `docs/instructions/workflows` (the feature-development and delivery-policy workflows) alongside `rules`, `stack`, and `design-system`. Previously the workflow policy files shipped but were never named by anything the agent loads, so they were never read. Regression guards assert the workflows dir stays in the load list in both the bootstrap and the entry-gate hooks.

## 1.30.1

### Patch Changes

- [#237](https://github.com/Eliyce/paqad-ai/pull/237) [`a0f527f`](https://github.com/Eliyce/paqad-ai/commit/a0f527ff27c8f1a1dfda26cc0c672806f51a90a9) Thanks [@HLasani](https://github.com/HLasani)! - Fix stale documentation references that pointed the workflow-policy files at `.paqad/workflows/` instead of their real home, `docs/instructions/workflows/`. The `rounds:` round-cap override is configured in `docs/instructions/workflows/feature-development.yaml` (`.paqad/workflows/` is the per-run records directory, a different thing). Adds a regression guard so a workflow-policy YAML can never again be referenced under `.paqad/workflows/`.

## 1.30.0

### Minor Changes

- [#233](https://github.com/Eliyce/paqad-ai/pull/233) [`8e667c7`](https://github.com/Eliyce/paqad-ai/commit/8e667c7d81954735f2c682f978d2a1e7b60da20f) Thanks [@HLasani](https://github.com/HLasani)! - Lean entry files: load the framework and contracts only when paqad is enabled ([#229](https://github.com/Eliyce/paqad-ai/issues/229))

  Provider entry files (`CLAUDE.md`, `AGENTS.md`, `GEMINI.md`, and the rest) are now lean stubs. Each one points to a new core-owned framework bootstrap and carries the graceful-degradation fallback clause, nothing more. The load order, the narration contract, and the Decision Pause Contract moved out of every project's `.paqad/` and into that bootstrap (`AGENT-BOOTSTRAP.md`, shipped inside the install), behind a first-instruction enablement check.

  What this changes for you:

  - A disabled project now loads zero `docs/instructions` and zero `docs/modules` on every provider, because the always-injected entry file no longer carries any load order. An enabled project is unchanged: full framework and docs load exactly as before, including the Claude Code decision tray and the `create documentation` workflow.
  - The two managed contract files (`.paqad/decision-pause-contract.md`, `.paqad/narration-contract.md`) are no longer written into projects. `onboard` and `refresh --providers` prune any stale copy left by an older version. Existing projects pick up the lean entry stubs on their next update or refresh.
  - The dashboard editor for the Decision Pause Contract is retired (the file is framework-owned now); the approvals inbox that resolves pending decisions is unchanged.

  Default stays on. Flipping `paqad_enable` back to true re-enables everything with no re-onboard.

## 1.29.1

### Patch Changes

- [#231](https://github.com/Eliyce/paqad-ai/pull/231) [`a873dd5`](https://github.com/Eliyce/paqad-ai/commit/a873dd574f2b1b5f8a48869d91a42f22034efd6a) Thanks [@HLasani](https://github.com/HLasani)! - Onboarding (and `update`) now also write a single `.paqad/.config.example` catalog alongside the per-group `configs/.config.*` files.

  `.config.example` lists every framework knob in one file, commented out at its default, with a one-line explanation and its `PAQAD_*` env equivalent — the same copy-paste reference Laravel's `.env.example` provides, so you never have to guess a variable name. It is tracked but never read at runtime; copy a line into a `configs/.config.*` (team) or `.config` (local) file, uncomment it, and set a value. The per-group files are unchanged.

## 1.29.0

### Minor Changes

- [#228](https://github.com/Eliyce/paqad-ai/pull/228) [`8522104`](https://github.com/Eliyce/paqad-ai/commit/8522104679eb304e8e622ded5f773f0f9281d787) Thanks [@HLasani](https://github.com/HLasani)! - Move framework configuration out of `project-profile.yaml` into a Laravel-style four-surface config layer.

  Framework knobs (the `paqad_enable` switch, `enterprise`, RAG/`intelligence`, `strictness`, `escalation`, `features`, `research`, `model_routing`, and decision tuning) are no longer project facts living in `project-profile.yaml`. Their defaults now live in code, and a team or developer overrides them through four surfaces, highest precedence last (local wins over team):

  1. framework code defaults (the `FRAMEWORK_CONFIG_SPECS` registry)
  2. `.paqad/configs/.config.*` — tracked, team-shared, merged grouped files (`.config.app`, `.config.rag`, `.config.models`, `.config.policy`)
  3. `.paqad/.config` — git-ignored, per-developer (local wins)
  4. `PAQAD_*` environment variables — per-run escape hatch

  Keys are bare and readable (`enterprise=true`); each maps to a `PAQAD_*` env equivalent (`PAQAD_ENTERPRISE`). Onboarding writes one self-documenting file per group, pre-filled with every knob in that group **commented out** at its default, with a one-line explanation and its env equivalent. Because every line is commented, a freshly onboarded project runs entirely on code defaults; you uncomment a line to override. `project-profile.yaml` keeps only project facts (name, commands, capabilities, stack, MCP servers).

  Adds two new knobs: `auto_update` (the canonical auto-update switch; `skip_version_check` is now a deprecated alias) and `minimum_version` (default `latest`; pin a version to force the background self-update past its throttle until the floor is met).

  `paqad-ai enable`/`disable` and the dashboard config surface read and write the config layer. The off-signal (`paqad_enable=false`, plus the `PAQAD_DISABLED` hard switch) is honored identically by all three enforcement primitives (the TS predicate, the shell kill switch, and the `.mjs` hook), pinned by a shared golden-fixture parity test.

  Onboarding and update reconcile, they never reset: `update` appends knobs a new version introduced (commented) to your existing group files and prunes keys a new version removed, but never changes a value you uncommented.

  Note for projects that hand-edited framework values in `project-profile.yaml`: this is a hard cutover, so those inline values are no longer read. Move any non-default settings into `.paqad/configs/.config.*` or `.paqad/.config` (every option is listed, commented out, in the `.paqad/configs/` files). Onboarding prints a one-time notice listing any non-default value it found so nothing reverts silently. Defaults are unchanged, so projects on defaults are unaffected.

## 1.28.1

### Patch Changes

- [#223](https://github.com/Eliyce/paqad-ai/pull/223) [`4ce2295`](https://github.com/Eliyce/paqad-ai/commit/4ce22959b54f148885dfea6c6580a375612f8b23) Thanks [@HLasani](https://github.com/HLasani)! - Preserve user config on re-onboard, always show the enable switch, and stop the dashboard in vanilla mode ([#220](https://github.com/Eliyce/paqad-ai/issues/220) follow-up)

  - **Re-onboard no longer clobbers config.** `paqad-ai onboard` now reads the
    existing `project-profile.yaml` and carries every user-set section forward
    (`enterprise`, `intelligence`/RAG, `paqad.enabled`, and the rest), only
    refreshing detection-derived fields (`active_capabilities`, `stack_profile`)
    and adding newly introduced keys. Previously a re-onboard reset those sections
    to defaults.
  - **The enable switch is always visible.** Onboarding now writes
    `paqad.enabled: true` into the profile so the global toggle is discoverable and
    editable, never a hidden default. Absent still resolves to ON for older
    profiles. Added `paqad` to the project-profile schema.
  - **Vanilla mode includes the dashboard.** `paqad-ai dashboard` (and the `graph`
    alias) no longer start the server when paqad is disabled
    (`paqad.enabled: false` or `PAQAD_DISABLED=1`); they print a short notice and
    exit.
  - Added a `config-visibility` rule so this contract (visible config, preserved on
    refresh) is durable.

## 1.28.0

### Minor Changes

- [#221](https://github.com/Eliyce/paqad-ai/pull/221) [`d0e93dd`](https://github.com/Eliyce/paqad-ai/commit/d0e93dd0d66dc27321ea7819b4736ff969ce072d) Thanks [@HLasani](https://github.com/HLasani)! - Add a global enable/disable toggle with graceful degradation ([#220](https://github.com/Eliyce/paqad-ai/issues/220))

  Teams can now turn paqad fully off for a fair A/B baseline, and an
  absent or disabled install can no longer hard-fail an IDE.

  - **One off-signal, read everywhere.** A committed `paqad.enabled: false`
    in `.paqad/project-profile.yaml`, or a per-run `PAQAD_DISABLED=1`
    override (which wins), turns paqad off. Absent means on, so existing
    projects are unchanged. The signal is read three dist-less ways that
    agree: a TS predicate, a shell primitive, and an `.mjs` primitive.
  - **Off is a pure no-op.** Both entry gates, the decision-pause gate, the
    completion hooks, the verification backstop, and silent-update all
    early-exit when off. No block, no `[paqad]` stdout injection, and zero
    `.paqad/` writes, so a disabled turn leaves a clean tree.
  - **No IDE dead-ends.** Every host entry file now carries a graceful
    fallback clause: if the framework pointer cannot be resolved or paqad is
    disabled, the agent proceeds as a normal assistant instead of blocking.
  - **`paqad-ai enable` / `paqad-ai disable`** flip the durable flag with no
    re-onboarding, and `paqad-ai doctor` reports the disabled (vanilla mode)
    state as healthy.

## 1.27.0

### Minor Changes

- [#207](https://github.com/Eliyce/paqad-ai/pull/207) [`c004f78`](https://github.com/Eliyce/paqad-ai/commit/c004f7805fd5af05ed9a03a6ccdb3072afb84143) Thanks [@HLasani](https://github.com/HLasani)! - Make an onboarded `.paqad/` directory lighter and the auto-update hook cross-platform.

  - **Cross-platform silent-update.** The session-start auto-update hook is now a Node `silent-update.mjs` that runs from the framework install, instead of a `silent-update.sh` copied into every project. The shell version needed bash, python3, and GNU coreutils; the Node version needs only Node, so auto-update works on minimal images and Windows. On re-onboard the old `.sh` entry is pruned from the provider config and the committed copy is removed.
  - **Stop churning the tracked manifest.** `onboarding-manifest.json` no longer carries `framework_version` (the one field that changed on every version bump). The file stays tracked for its auto-update policy and onboarded-sentinel role.
  - **Drop zero-reader artifacts.** `.paqad/version`, `.paqad/classifier-config.json`, and `.paqad/next-steps.md` are no longer written (the next-steps guidance is printed to the terminal at the end of onboarding). Repos onboarded before this change have these untracked and removed on re-onboard.
  - **Quieter module health.** Profiles are created on demand as modules accrue evidence instead of seeding an empty profile per module at onboard, and consumed evidence files are deleted after they fold into a profile, so they no longer grow unbounded.
  - **Close .gitignore gaps.** Per-machine runtime state created on first use of a later workflow (`patterns/`, `crs/`, `attachments/`, `traceability/`, module-map drift/events, and more) is now ignored so it never churns a team repo.
  - **Fewer false health warnings.** The decision-workspace check no longer requires the git-ignored audit log, and a missing module-health directory is treated as healthy.

## 1.26.2

### Patch Changes

- [#196](https://github.com/Eliyce/paqad-ai/pull/196) [`e92a757`](https://github.com/Eliyce/paqad-ai/commit/e92a75707dd06973b84b33be1eb404ba3f91de54) Thanks [@HLasani](https://github.com/HLasani)! - fix: produce the evidence ledger on every provider, not Claude Code alone

  The verification-completion run that writes `.paqad/ledger/` only fired from Claude Code's native `Stop` hook, so onboarded projects driven by Codex, Gemini, or any other host produced no evidence ledger even with `enterprise.evidence_ledger` enabled. The completion hook was rendered into Claude's config alone; every other adapter wrote inert hook metadata its host never executes.

  Each hook-capable host now gets its native completion hook wired during onboarding, from one shared definition (`src/adapters/shared/native-completion-hook.ts`): Codex `Stop` in `.codex/hooks.json`, Gemini `AfterAgent` in `.gemini/settings.json`. They point at a new record-only runtime hook (`runtime/hooks/verification-record.mjs`) that writes the ledger but always exits 0 and stays silent, so a host that reads a Stop-hook's exit code or stdout never gets blocked or retried. No change to any host's entry file (`AGENTS.md` / `GEMINI.md`) — the fix lives entirely in the hook layer. Hosts without a native completion hook remain covered by the git/CI backstop. A new `docs/instructions/rules/coding/cross-provider-parity.md` rule and a cross-adapter parity test guard against a capability being wired for a single host again. Cursor and Windsurf native hooks are tracked as follow-up.

## 1.26.1

### Patch Changes

- [#194](https://github.com/Eliyce/paqad-ai/pull/194) [`8885a27`](https://github.com/Eliyce/paqad-ai/commit/8885a27083898032206225e8483ee03cc89843a8) Thanks [@HLasani](https://github.com/HLasani)! - Ignore the rule-script snapshot directory `.paqad/scripts/rules/.history/` in the managed `.paqad/.gitignore`. It holds per-machine pre-mutation rule snapshots and an events log (the same runtime category as the already-ignored `.cache/` sibling) and should never be committed.

## 1.26.0

### Minor Changes

- [#192](https://github.com/Eliyce/paqad-ai/pull/192) [`ab0e7de`](https://github.com/Eliyce/paqad-ai/commit/ab0e7de7cc449ff0b8fcfc1bb7402cb16bfd906a) Thanks [@HLasani](https://github.com/HLasani)! - Make onboarded repos' git hygiene self-contained and correct. paqad now manages its ignore policy inside `.paqad/` (a nested `.paqad/.gitignore` + `.paqad/.gitattributes`) instead of editing the project's root `.gitignore`; re-onboarding scrubs the old paqad-managed block out of the root file. Three policy fixes ship with the move: the boot pointer `framework-path.txt` now stays committed so a teammate can clone and boot without re-onboarding; the per-machine `framework-version.txt` is now git-ignored so silent self-updates no longer churn the tree (the silent-update hook recreates it locally on first session); and `.paqad/ledger/` is now ignored unconditionally so enabling the enterprise ledger can never leak evidence into git. The health check resolves "is this ignored?" via git (honoring the nested file) and no longer treats the local version file as a required committed artifact.

## 1.25.1

### Patch Changes

- [#190](https://github.com/Eliyce/paqad-ai/pull/190) [`b8411de`](https://github.com/Eliyce/paqad-ai/commit/b8411de3325db11c950be53ef40f2097e85b6e7b) Thanks [@HLasani](https://github.com/HLasani)! - Fix onboarding to emit the `enterprise` block in the generated `project-profile.yaml`, and remove the two never-wired feature flags.

  - **Onboarding now writes the `enterprise` block** (`enabled`, `evidence_ledger`, `ai_bom`, `compliance_citations`, all `false`). The opt-in evidence-ledger switches from [#187](https://github.com/Eliyce/paqad-ai/issues/187) were previously invisible in a freshly onboarded profile, so users had nothing to toggle. Defaults stay all-off: a normal user pays zero tokens and writes nothing under `.paqad/ledger/`.
  - **Removed `features.supply_chain_governance` and `features.ai_governance`.** These were declared in the profile type and schema but read by no code path, and their names collided conceptually with the now-real `enterprise.*` governance switches. Dropped from the `ProjectFeatureFlags` type, the JSON schema, the onboarding default, and all test fixtures.

  Not a runtime break: `readProjectProfile` tolerates extra keys, so existing on-disk profiles that still contain the two removed flags continue to load (the stale keys are ignored).

## 1.25.0

### Minor Changes

- [#188](https://github.com/Eliyce/paqad-ai/pull/188) [`690ce1e`](https://github.com/Eliyce/paqad-ai/commit/690ce1e80f44c95c7027f8af2df973c9734de11c) Thanks [@HLasani](https://github.com/HLasani)! - Gate the evidence ledger behind an opt-in `enterprise` config block (disabled by default).

  `.paqad/ledger/` machinery (`evidence.jsonl`, `receipts.jsonl`, `receipt.dsse.json`, `ai-bom.json`) and the token-spending compliance-citation resolution now only run when a project opts in via `enterprise:` in `.paqad/project-profile.yaml`. With the block absent — the default for every existing and new project — a verification run writes no ledger files and resolves no citations, so a normal user pays zero tokens and gets a clean working tree.

  ```yaml
  enterprise:
    enabled: false # master switch; when false every sub-flag is forced off
    evidence_ledger: false # evidence.jsonl + receipts.jsonl + receipt.dsse.json
    ai_bom: false # ai-bom.json (CycloneDX); independent of evidence_ledger
    compliance_citations: false # framework citations baked into the receipt
  ```

  `enabled: true` turns the sub-flags into independent switches (e.g. AI-BOM without the full receipt set). The new `src/core/enterprise-policy.ts` resolver is the single seam a future license/token check slots behind. Onboarding only adds `.paqad/ledger/` to the managed `.gitignore` when the ledger is enabled. Verification verdicts are unaffected — ledger failures remain warnings, never blocks.

## 1.24.0

### Minor Changes

- [#185](https://github.com/Eliyce/paqad-ai/pull/185) [`2bec5ec`](https://github.com/Eliyce/paqad-ai/commit/2bec5eca66ec4aad7b9541d5ddd99f538102b6df) Thanks [@HLasani](https://github.com/HLasani)! - Make onboarded repos team-safe so parallel branches no longer collide.

  - Decision IDs are now collision-free ULIDs (`D-<ULID>` / `MD-<ULID>`) instead of monotonic counters, so two developers raising decisions on diverged branches mint different filenames and merge cleanly. Existing `D-1`/`MD-0001` files keep loading, resolving, and listing unchanged.
  - The `.gitignore` paqad section is now a reconciling managed block that updates on re-onboard (previously it bailed the moment it saw its marker and never shipped new entries). It quarantines per-machine runtime state, the compliance ledger, and all module-health from version control.
  - Re-onboarding untracks any now-ignored path an earlier onboarding had committed, keeping the working-tree files.
  - Onboarding writes a managed `.gitattributes` block so the shared decision index merges by union.

## 1.23.1

### Patch Changes

- [#181](https://github.com/Eliyce/paqad-ai/pull/181) [`21c2d82`](https://github.com/Eliyce/paqad-ai/commit/21c2d82227e23c9228c127bf029053573fba9c82) Thanks [@HLasani](https://github.com/HLasani)! - Fix `module-health rollup` resolving zero stack packs. `source-roots.ts` shipped a local `resolveRuntimeRoot()` that returned the _parent_ of `runtime/` instead of `runtime/` itself, so `StackPackLoader` looked under `<packageRoot>/capabilities` (which does not exist), loaded no packs, and every `discoverModuleHealth`/`discoverSourceRoots` call returned `null` — hard-blocking the rollup with `module_health_unknown`. It now uses the canonical `getRuntimeRoot()`, matching every other framework caller, so module-health refresh resolves the active pack's `module_health` block correctly.

## 1.23.0

### Minor Changes

- [#179](https://github.com/Eliyce/paqad-ai/pull/179) [`c53d01d`](https://github.com/Eliyce/paqad-ai/commit/c53d01da5468042cb0e7160e2192922052db9aca) Thanks [@HLasani](https://github.com/HLasani)! - Module health now updates instead of staying frozen at the onboarding stub.

  Two changes close the gap that left every module's `.paqad/module-health/<slug>.json` reading `tier: unknown` with all metrics null after onboarding:

  - The verification backstop (`runRepositoryVerification`) now folds verification reality into each touched module's health profile on every completion. This is the agent-independent chokepoint behind the Claude Stop hook and the git/CI backstop, so profiles refresh automatically with no change required in onboarded projects.
  - A new `update module health` workflow (routed like `create documentation`) refreshes every module on demand. It runs a rollup then a sync across all declared modules and reports each module's resulting tier. It wraps the existing `module-health rollup` and `module-health sync` commands and adds no new CLI command.

## 1.22.2

### Patch Changes

- [#177](https://github.com/Eliyce/paqad-ai/pull/177) [`ea8c367`](https://github.com/Eliyce/paqad-ai/commit/ea8c36722c84ac82c486e5dbaf9dad0cc9d9bac5) Thanks [@HLasani](https://github.com/HLasani)! - Fix the AI bill of materials on the dashboard.

  Two problems made the BOM unreadable. First, `git status --short` parsing left-trimmed each line before slicing the status columns, which dropped the first character of every worktree-only changed path (`package.json` became `ackage.json`). That corrupted the BOM component names, their file digests, and the change-completeness gate messages. Second, the dashboard BOM panel only showed a file count, never the files themselves. The panel now lists every attested file with its SHA-256 digest, and shows a clear empty state when the latest verified change touched no files.

- [#177](https://github.com/Eliyce/paqad-ai/pull/177) [`ea8c367`](https://github.com/Eliyce/paqad-ai/commit/ea8c36722c84ac82c486e5dbaf9dad0cc9d9bac5) Thanks [@HLasani](https://github.com/HLasani)! - Restore the executable bit on the installed runtime hooks and scripts.

  The package is published with `changeset publish`, which packs the tarball with pnpm. pnpm normalises every file mode to `0644` and drops the executable bit (npm preserves it), so on an installed copy the host agent could not run any runtime hook: invoking `~/.paqad-ai/current/hooks/verification-completion.mjs` failed with "permission denied". The visible symptom was that the verification backstop never fired for onboarded projects, so the evidence ledger, receipts, AI-BOM, and the local dashboard data were never produced. A `postinstall` step now re-adds the executable bit on every install and update, with no action required from the user.

## 1.22.1

### Patch Changes

- [#174](https://github.com/Eliyce/paqad-ai/pull/174) [`8ad856b`](https://github.com/Eliyce/paqad-ai/commit/8ad856b5c02d7a32ccc7113aa811f2777a5e3985) Thanks [@HLasani](https://github.com/HLasani)! - Collapse the in-chat narration contract in provider entry files to a one-line pointer ([#173](https://github.com/Eliyce/paqad-ai/issues/173)). The full voice spec stays in the canonical `.paqad/narration-contract.md`; the entry files (CLAUDE.md, AGENTS.md, and every adapter) now carry only the heading plus a pointer line, matching the Decision Pause Contract shape. `paqad refresh --providers` rewrites already-onboarded projects down to the pointer.

## 1.22.0

### Minor Changes

- [#171](https://github.com/Eliyce/paqad-ai/pull/171) [`1cc8535`](https://github.com/Eliyce/paqad-ai/commit/1cc85357813d0dd050b17c751e04ee07752b8934) Thanks [@HLasani](https://github.com/HLasani)! - North Star Dashboard: the project graph becomes a trust-building, first-class dashboard area (epic [#166](https://github.com/Eliyce/paqad-ai/issues/166)).
  - Graph is now a dashboard area served by the dashboard server itself (read-only `/api/graph`, `/api/node/:id`, `/api/chunk/:id/content`, `/api/similar`); the standalone `paqad-ai graph` command is a deprecated alias that opens the dashboard on the Graph view.
  - Trust gains a SIEM export panel (`GET /api/export/siem`, OCSF/ECS/CEF/JSONL), byte-identical to `paqad-ai audit export`.
  - Project-scoped saved views (graph, Trust filter, SIEM export config) and access-free static HTML snapshots of receipts and modules.
  - The graph leads with a clean, health-coloured map of named areas with an authored headline, reveals files and deeper detail only on zoom, and moves the engineer controls behind an Advanced disclosure.
  - Plain-language node detail cards (what it is, how it is doing, what the AI changed, what to do), with the raw fields behind a For engineers disclosure.
  - An AI-activity overlay projected from the verification receipts lights the areas AI agents touched, links each to its receipt, states the problem and the fix for at-risk areas, and offers a board-safe Shareable view.

## 1.21.0

### Minor Changes

- [#167](https://github.com/Eliyce/paqad-ai/pull/167) [`f852189`](https://github.com/Eliyce/paqad-ai/commit/f852189f4dfcf0df264b6af638e804213c47cde2) Thanks [@HLasani](https://github.com/HLasani)! - Give paqad a visible voice in the live agent chat. Onboarding now bakes a "paqad in your chat" narration contract into every provider entry file (CLAUDE.md, AGENTS.md, .cursor/rules, and the rest), instructing the agent to surface paqad's orchestration work — classification, lane routing, verification verdicts, decision pauses — in a lean, first-person, value-anchored voice. The glyphs (🟢🔴🟡⚪), verdict words, status-block frame, and plain-English term translations are defined once in a canonical voice spec and reused by the PR evidence comment, the dashboard, and the chat contract, plus a managed `.paqad/narration-contract.md` reference doc. A health check flags a missing or drifted contract.

## 1.20.0

### Minor Changes

- [#156](https://github.com/Eliyce/paqad-ai/pull/156) [`6cf600c`](https://github.com/Eliyce/paqad-ai/commit/6cf600cc36888edd6eeae66eb103a3e620372e50) Thanks [@HLasani](https://github.com/HLasani)! - Complete the verifiable-trust receipt with two optional, additive fields ([#122](https://github.com/Eliyce/paqad-ai/issues/122),
  [#123](https://github.com/Eliyce/paqad-ai/issues/123)). Both fold into the existing [#118](https://github.com/Eliyce/paqad-ai/issues/118) receipt + [#146](https://github.com/Eliyce/paqad-ai/issues/146) Trust dashboard the same
  way [#120](https://github.com/Eliyce/paqad-ai/issues/120) authorship did, and are omitted when absent so receipts for projects
  without them stay byte-identical.

  **[#122](https://github.com/Eliyce/paqad-ai/issues/122) — gate→clause compliance citations.** A new `compliance-pack` kind (its
  own registered schema, `kind` discriminator, OSCAL relation vocabulary,
  `evidence_strength` that rejects `full`) maps verification gates to legal-
  framework clauses. At verification time, a clause is cited only when every gate
  it depends on **passed** (never inconclusive/blocked), so a green gate can cite
  which EU AI Act / NIST / ISO clause it produces _evidence toward_ — never a
  claim of compliance. Ships an honest built-in EU AI Act pack and surfaces clause
  chips + the pack's disclaimer on the receipt, the Trust dashboard, and the PR
  comment. Project packs override built-ins via the usual precedence.

  **[#123](https://github.com/Eliyce/paqad-ai/issues/123) — reproducibility stamp.** Promote paqad's deterministic context rebuild
  hash into `computeContextHash`: a SHA-256 over a canonical, key-ordered,
  explicitly-versioned preimage (lineage, classifier output, retrieved-chunk
  digests, budget, summariser mode, truncation), exposed as `contextHash` on the
  rebuild result and recorded in a durable `context-stamp.json`. The receipt then
  asserts `determinism: 'input-replay'` — the context an agent saw is replayable
  from these exact inputs. It deliberately does **not** claim bit-identical LLM
  regeneration (hosted models expose no stable seed; temperature 0 is still
  non-deterministic).

## 1.19.0

### Minor Changes

- [#154](https://github.com/Eliyce/paqad-ai/pull/154) [`a709140`](https://github.com/Eliyce/paqad-ai/commit/a70914026595dbb6f6adc20a174bbbed706d62ea) Thanks [@HLasani](https://github.com/HLasani)! - Add `paqad-ai audit export` — a read-only, local-first exporter that projects the
  unified evidence ledger and tamper-evident receipt chain ([#118](https://github.com/Eliyce/paqad-ai/issues/118)/[#120](https://github.com/Eliyce/paqad-ai/issues/120)) into the
  SIEM schemas enterprises already ingest: OCSF (primary), Elastic ECS, ArcSight
  CEF, and a canonical JSONL passthrough.

  `paqad-ai audit export --format=ocsf|ecs|cef|jsonl [--since <iso>] [--out <file>] [--redact]`
  reads the on-disk ledger, normalizes each graded verdict and signed attestation
  (verdict, deterministic-vs-LLM-judged grade, change-subject digests, chain seal
  status, and change authorship) into the target schema, and writes a file or
  stdout for the customer's own collector (Splunk forwarder, rsyslog, Datadog
  agent, Filebeat) to ship. There is no paqad-hosted endpoint — their backend, our
  data. `--redact` strips free-text detail and human identities for a lower-PII
  export.

## 1.18.0

### Minor Changes

- [#153](https://github.com/Eliyce/paqad-ai/pull/153) [`e3f2377`](https://github.com/Eliyce/paqad-ai/commit/e3f237740e201e5019f5d0514f1460011eda917c) Thanks [@HLasani](https://github.com/HLasani)! - Complete the dashboard editing surface: every web-managed setting is editable on the web ([#146](https://github.com/Eliyce/paqad-ai/issues/146) phase 3).

  New editors, all through the audited write pipeline: the instructions
  editor in Knowledge (file tree, CodeMirror with frontmatter as fields,
  markdown preview, the 409 diff prompt), the module map editor in Build
  (structured table, raw YAML editor of record, drift findings inline with
  one-click reconcile), the design token editor (swatch grid, raw JSON, live
  preview, derived docs regenerated on save), the profile schema form,
  capability toggles, pack install and remove, the decision pause contract,
  and the RAG settings panel.

  Safe operations run as jobs through the same code paths as the CLI:
  reconcile, refresh rules, refresh context, rebuild or clear the RAG index,
  regenerate design docs, compliance check, and doctor. Progress streams over
  SSE as `ops-progress`, double-starts of the same action answer 409, and
  every finished job lands in the audit log.

  Also new: `GET /api/audit` (the filterable audit feed),
  `GET /api/onboarding-checklist` (real-event completion states), and
  `GET /api/export/evidence-packet` (a self-contained HTML, Markdown, and
  JSON trust bundle).

- [#153](https://github.com/Eliyce/paqad-ai/pull/153) [`e3f2377`](https://github.com/Eliyce/paqad-ai/commit/e3f237740e201e5019f5d0514f1460011eda917c) Thanks [@HLasani](https://github.com/HLasani)! - Finish the dashboard onboarding and polish slice ([#146](https://github.com/Eliyce/paqad-ai/issues/146) phase 4).

  The command palette opens on Cmd+K (and Ctrl+K) and jumps to any area,
  editor, or action. Pulse gains the onboarding checklist driven by real
  events, never clicks: connect your agent, watch your first gate pass,
  approve your first decision, open your first receipt, edit one instruction
  file. It completes itself from artifacts on disk, teaches the palette in
  step one, and signs off with a single win line. Pulse also gains the recent
  activity feed, rendered as sentences rather than log lines.

  Trust gains the receipt seal animation (the product's only spring, 300ms,
  played once when a new receipt arrives live) and two export actions: open
  the evidence packet as standalone HTML, or copy its Markdown for a PR or a
  release note.

- [#151](https://github.com/Eliyce/paqad-ai/pull/151) [`226ac1f`](https://github.com/Eliyce/paqad-ai/commit/226ac1f453b2094d3e801d6e23afc36471d1670e) Thanks [@HLasani](https://github.com/HLasani)! - Give the dashboard the seven-area management IA and the comprehension layer ([#146](https://github.com/Eliyce/paqad-ai/issues/146) phase 3, first slice).

  The dashboard now opens on Pulse and organizes everything the spec's
  management rule describes into seven areas behind a quiet, collapsible left
  sidebar: Pulse, Approvals, Trust, Build, Automation, Knowledge, Setup. The
  legacy all-sections health view stays reachable at `#/dashboard` and the
  architecture graph keeps `#/graph`, reached from Build.

  A new `GET /api/inventory` endpoint classifies every paqad functionality
  exactly once as web-managed, prompt-managed, evidence, or a safe operation,
  with its owner, live on-disk state, and the area page that renders it. Area
  pages draw their cards entirely from this report, so the three-way
  classification lives in one place.

  The comprehension layer ships with it: an ownership badge on every card (You
  manage this, Paqad manages this, Shared), a why-sentence under every title, a
  "Why this matters" drawer with the problem, the benefit, and what happens
  without it, and empty states that teach. All copy follows the spec's voice
  pack verbatim.

- [#152](https://github.com/Eliyce/paqad-ai/pull/152) [`7ac4c43`](https://github.com/Eliyce/paqad-ai/commit/7ac4c437ff617d3c7e49fb704bfe87795b3568e0) Thanks [@HLasani](https://github.com/HLasani)! - Add the audited write pipeline and the first full web editor: the delivery policy rule builder ([#146](https://github.com/Eliyce/paqad-ai/issues/146) phase 3).

  Every dashboard file mutation now runs one pipeline: validate (ajv for
  schema-backed files, YAML parse otherwise), enforce the path allowlist (only
  `docs/instructions/**` and the named config files; no traversal, no
  dotfiles, symlinks resolved and rejected outside the project root), check
  the content hash the client loaded (a mismatch returns 409 with the current
  content for a side-by-side diff), write atomically, and append
  `actor="dashboard"` with the content hash to `.paqad/audit.log`. Edits under
  `docs/instructions/**` invalidate the agent entry sentinel through the
  existing mtime gates, so every agent reloads the canonical context next
  session.

  The delivery policy gets the spec's rule builder at `#/delivery-policy`:
  one card per process section with a "Paqad keeps this in sync" / "You own
  this" toggle, typed fields, and a plain-language preview line under each
  section. A raw YAML mode covers everything else, and structured edits go
  through a YAML document so comments survive. Saving validates against the
  delivery-policy schema and answers with the win line. The instructions file
  tree and file read/write endpoints land server-side for the Knowledge
  editor that follows.

  New endpoints: `GET/PUT /api/config/delivery-policy`,
  `GET /api/files/instructions`, `GET/PUT /api/files/instructions/{path}`.
  All mutations sit behind the existing guardrails, including `--read-only`.

### Patch Changes

- [#148](https://github.com/Eliyce/paqad-ai/pull/148) [`7b3146c`](https://github.com/Eliyce/paqad-ai/commit/7b3146c109374147ac22d231a0406d9844f39cfc) Thanks [@HLasani](https://github.com/HLasani)! - Stop the dashboard audit-log feedback loop on legacy project profiles.

  On projects whose `.paqad/project-profile.yaml` predates the canonical
  capabilities model, `readProjectProfile` could flag a profile as "migrated"
  even when the canonical rewrite was byte-identical (a declared `coding`
  capability with no usable stack profile). Every read then re-appended the
  "Migrated project profile to canonical capabilities model" line to
  `.paqad/audit.log`. With `paqad-ai dashboard` running, the `.paqad/` watcher
  saw each append, rebuilt the report, read the profile again, and looped
  roughly every 500ms, growing the audit log forever and firing the SSE
  `dashboard-updated` stream continuously.

  Two changes close the loop:
  - Profile migration now reports `migrated` only when the canonical form
    actually differs from what is on disk. `coding` active without a stack
    profile is treated as a valid converged state (stack detection may simply
    not have run yet), so the migration converges after a single write.
  - The `.paqad/` watcher ignores append-only logs the report build and
    dashboard mutations write themselves (`audit.log`, `logs/`), so a log
    append can never re-trigger the build that produced it.

- [#149](https://github.com/Eliyce/paqad-ai/pull/149) [`3b9bf40`](https://github.com/Eliyce/paqad-ai/commit/3b9bf40c5d2fcba2f120b05ee79eb41672d4f170) Thanks [@HLasani](https://github.com/HLasani)! - Make the shipped skill scripts portable to Debian and immune to a SIGPIPE race.

  Two real defects surfaced by running the test suite in `node:22-bookworm`
  and `node:24-bookworm` containers:
  - Debian's default awk is mawk, which silently fails to match `{n,m}`
    interval expressions. The copy-and-ia-review scripts used intervals inside
    awk `match()` calls, so `extract-user-strings.sh` dropped every jsx-text
    row and `check-action-verbs.sh` produced no output on Debian while
    gawk-based CI stayed green. The awk patterns now use `+` with an explicit
    `length()` cap, and a guard test rejects any future awk `match()` interval.
  - Under `set -o pipefail`, `printf '%s' "$body" | grep -qE pattern` fails
    with status 141 exactly when the pattern matches early: `grep -q` exits on
    first match and printf dies of a silent SIGPIPE. The `|| say` validation
    idiom then recorded a plausible-looking finding, which is why lint scripts
    intermittently rejected valid input on loaded runners. All 166 occurrences
    across 60 scripts now use herestrings (`grep -q pattern <<<"$var"`), which
    cannot race, and a guard test keeps pipelines from feeding `grep -q` again.

  The test harness retry gate also tightened: it retries only results with no
  output at all (or infrastructure-flavored stderr), so specs that expect a
  non-zero exit no longer burn the full backoff, and a `PAQAD_DEBUG_RUNSCRIPT`
  hook records non-zero results for future flake forensics.

## 1.17.0

### Minor Changes

- [#147](https://github.com/Eliyce/paqad-ai/pull/147) [`f38179b`](https://github.com/Eliyce/paqad-ai/commit/f38179b8ba5289feea5a7cd3ed21ec36ab410403) Thanks [@HLasani](https://github.com/HLasani)! - Add the approvals inbox and trust area to the dashboard ([#146](https://github.com/Eliyce/paqad-ai/issues/146), scoped).

  The dashboard gains two surfaces on top of the existing health view, for
  onboarded projects:

  **Approvals** is one inbox for everything waiting on the human: decision
  pauses and proposed MD-XXXX module decisions, each with consequence lines per
  option. Resolving on the web writes through the same `DecisionStore` and
  module-decision state machine the agent uses, so the conversation picks the
  answer up on its next tool call. Every web mutation is recorded with
  `actor="dashboard"` in `.paqad/audit.log`.

  **Trust** renders the proof: the evidence ledger as a filterable timeline, DSSE
  receipts as cards with per-link seal verification and authorship, the
  CycloneDX AI-BOM with download, and a "Copy as PR comment" action that emits
  the exact Markdown `paqad-ai evidence` prints. View and export only, by
  design.

  Mutations are guarded: onboarded projects only, loopback host and same-origin
  checks, 64 KB body cap, and a new `paqad-ai dashboard --read-only` flag that
  disables every mutation endpoint for shared or CI usage.

  Issue [#146](https://github.com/Eliyce/paqad-ai/issues/146)'s full editing surface (web editors for instructions, workflows,
  policies, tokens) is deliberately deferred; the scope decision and the market
  evidence behind it are recorded in `docs/design/dashboard-approvals-trust.md`.

### Patch Changes

- [#144](https://github.com/Eliyce/paqad-ai/pull/144) [`12cccfb`](https://github.com/Eliyce/paqad-ai/commit/12cccfb46d67af1a69edcc4b1a710b1e18535766) Thanks [@HLasani](https://github.com/HLasani)! - Stop shipping a duplicated environment rule and guard against it recurring ([#94](https://github.com/Eliyce/paqad-ai/issues/94)).

  The `node-service` stack's "Environment Variable Management" rules restated the
  typed-config, fail-fast, `.env.example`, and safe-default guidance that the
  always-on `_shared/environment.md` rule already ships to the same project, so
  onboarded node-service projects received the same guidance twice. That section
  is collapsed to the one node-specific rule that sharpens the shared contract.

  A new regression guard in `rule-quality.test.ts` compares every stack rule
  against the always-on base, capability, and `_shared` rules that ship alongside
  it and fails when a stack rule near-verbatim repeats one — a stack rule may
  sharpen an always-on rule with stack-specific detail but must not duplicate it.
  The contract is documented in `runtime/rules-authoring.md`.

## 1.16.0

### Minor Changes

- [#142](https://github.com/Eliyce/paqad-ai/pull/142) [`4dbc2b2`](https://github.com/Eliyce/paqad-ai/commit/4dbc2b2e349ff2bf13b56627aab08cb7e955f807) Thanks [@HLasani](https://github.com/HLasani)! - Fix and enforce silent self-update so onboarded installs actually stay current.

  The session-start update hook was effectively dead: it was never wired into the
  Claude Code `SessionStart` hooks, and even when run it only regenerated project
  artifacts via `npx paqad-ai@latest update` — it never upgraded the globally
  installed CLI, so a user's `paqad-ai` version never changed. On macOS it was
  doubly broken because the hook depended on GNU-only `timeout` and `flock`, which
  are absent on stock macOS, so the version check silently no-opped every session.

  Now:
  - `silent-update.sh` is registered as a Claude Code `SessionStart` hook on
    onboard/refresh, so the check runs every session.
  - When a newer version exists it runs the real upgrade —
    `npm install -g paqad-ai@latest` followed by `paqad-ai update --silent` — in
    the background. It never blocks, prompts, or prints to the user.
  - A two-minor-version policy is enforced: the allowed window is the latest minor
    and the one before it within the same major. Anything older (a minor beyond
    the band, or an older major) is classified as a `forced` update in the audit
    log so stale installs are visible.
  - The hook now resolves the project root from `CLAUDE_PROJECT_DIR`/`pwd` and
    degrades gracefully when `timeout`/`flock` are missing (`gtimeout`/bare `npm`
    and an atomic-`mkdir` lock with stale-lock reaping), so it works on macOS.

## 1.15.0

### Minor Changes

- [#140](https://github.com/Eliyce/paqad-ai/pull/140) [`a4a3c6d`](https://github.com/Eliyce/paqad-ai/commit/a4a3c6d7d2a31a1366618fe53ae7b846da03626c) Thanks [@HLasani](https://github.com/HLasani)! - Become the neutral, cross-agent attestation authority (issue [#120](https://github.com/Eliyce/paqad-ai/issues/120)).

  The [#118](https://github.com/Eliyce/paqad-ai/issues/118) receipt now records change authorship: which onboarded adapter wrote the change (a known fact), the declared model/provider (env-supplied, graded `provenance: 'declared'` so a routed model is never mistaken for a verified one), and the human who accepted it (git identity, suppressible via `PAQAD_NO_HUMAN_ATTESTATION`). Because paqad's trust signal is gate-derived, the attestation vouches for the change regardless of which AI tool produced it. Field names mirror the cross-vendor `agent-trace` convention (`model_id` = `provider/model`) so the record interoperates with that ecosystem rather than competing with it. Authorship is folded into the signed VSA predicate, flattened into `paqad:authorship:*` AI-BOM properties, rendered as a one-line PR-comment footer, and summarised in the dashboard's new Attestation section. When no authorship resolves the field is omitted entirely, so prior receipts stay byte-identical.

## 1.14.0

### Minor Changes

- [#138](https://github.com/Eliyce/paqad-ai/pull/138) [`2cfd738`](https://github.com/Eliyce/paqad-ai/commit/2cfd7387edc70b87543db65a02e49e5144b9a3b7) Thanks [@HLasani](https://github.com/HLasani)! - `paqad-ai evidence` — render verification evidence as a scannable PR comment ([#119](https://github.com/Eliyce/paqad-ai/issues/119)).

  paqad already computes a fully-typed `VerificationEvidence` per run (per-gate
  pass/fail, mutation kill-rate + confidence, test failures with `file:line`) and
  persists it to `.paqad/session/verification-evidence.json` — but nothing ever
  rendered it for a human. The new read-only command turns that JSON into a short
  green/red markdown summary you can pipe straight to `gh pr comment`:

  ```
  paqad-ai evidence $(git rev-parse HEAD) --output evidence.md \
    && gh pr comment --body-file evidence.md
  ```

  - Headline is driven by `overall_status` (🟢 Safe to merge / 🔴 Needs your
    attention), with the three trust-bearing gates (tests, mutation, quality
    ratchet) surfaced verbatim and every blocking failure pinned to `file:line`.
  - Numbers are rendered straight off each gate's `detail` string, so the comment
    never claims a figure the evidence does not hold. Lower-confidence mutation
    results are flagged, never hidden.
  - The footer honestly attests "paqad's gates passed for this run, not that the
    change is correct" — the human-readable counterpart to the signed receipt
    from [#118](https://github.com/Eliyce/paqad-ai/issues/118), not a replacement for it.
  - `--format json` re-emits the evidence, `--output <path>` writes a file, and
    `--fail-on-red` exits non-zero in CI when the overall status is fail.

  Output is deterministic: identical evidence yields a byte-identical comment.
  The command computes nothing, gates nothing, and signs nothing — it only
  surfaces what verification already produced.

  **Auto-post for every onboarded project.** The same render is now posted to
  the PR automatically by the delivery CI gate ([#42](https://github.com/Eliyce/paqad-ai/issues/42)), so the proof lands without
  anyone running a command. The provider-neutral `HostProvider` contract gains a
  `comment()` capability (GitHub adapter: `gh pr comment`), completing the
  previously half-built `on_red: comment_and_stop` intent. The gate posts the
  evidence on green (the "safe to merge" proof) and on a `comment_and_stop` red
  (the proof of what blocked it). Posting is best-effort — a failed comment never
  changes the gate verdict — and self-disables when no evidence exists.

## 1.13.1

### Patch Changes

- [#136](https://github.com/Eliyce/paqad-ai/pull/136) [`6c53e5a`](https://github.com/Eliyce/paqad-ai/commit/6c53e5aa937336ec0221c81391f2761b2896b6e6) Thanks [@HLasani](https://github.com/HLasani)! - Full Windows support. Fixed every Windows-only failure tracked in [#43](https://github.com/Eliyce/paqad-ai/issues/43)-[#53](https://github.com/Eliyce/paqad-ai/issues/53) plus the follow-ups it surfaced: path outputs are now forward-slash everywhere (RAG file discovery, evidence retrieval, planning doc targets, pentest reports and retests, rule scripts, delivery policy, module-map snapshots, pack manifests), custom workflow execution artifacts no longer use characters that are illegal in Windows filenames, and onboarding re-runs stay byte-identical on Windows. The windows-latest leg now runs as a full CI gate.

## 1.13.0

### Minor Changes

- [#133](https://github.com/Eliyce/paqad-ai/pull/133) [`51e5904`](https://github.com/Eliyce/paqad-ai/commit/51e5904f38b854c51dbc5e92150ff4b947f0810e) Thanks [@HLasani](https://github.com/HLasani)! - Provider-agnostic delivery workflow ([#42](https://github.com/Eliyce/paqad-ai/issues/42)). The `ticket_intake` → `delivery`
  loop is now configured by a standalone `delivery-policy.yaml` — a workflow-policy
  peer of `feature-development.yaml` (same location, schema validation, and
  `merge_mode: append` precedence) — on by default with every section
  `maintained: auto | manual`.
  - **Two provider-neutral contracts**: `TicketProvider` (Jira adapter) and
    `HostProvider` (GitHub adapter), resolved from config + the MCP `kind`
    discriminator. Linear / GitLab / Bitbucket are additive adapters.
  - **Conventions are detected from git history** and silently fill the `auto`
    sections during `create documentation`, with an end-of-docs summary and one
    combined "connect GitHub + Jira" nudge. Detection persists to
    `.paqad/delivery-detection.json`; the commented policy file is never rewritten.
  - **CI-wait gate** (`wait_for_green` / `warn_only` / `off`) with timeout and
    `on_red` handling, plus **graceful degradation** when a provider is not
    connected (git-only steps still run; provider-bound steps are skipped and
    re-nudged — never a hard stop).
  - New **Delivery Workflow** dashboard section showing configured/active state and
    the GitHub/Jira connection.

  The old `conventions:` block in the project profile is replaced by
  `delivery-policy.yaml`.

## 1.12.0

### Minor Changes

- [#131](https://github.com/Eliyce/paqad-ai/pull/131) [`2cdfbcf`](https://github.com/Eliyce/paqad-ai/commit/2cdfbcf0c0c3557fc7fea08a358ae16057befaf6) Thanks [@HLasani](https://github.com/HLasani)! - Add the unified evidence ledger and a signed, gradeable per-change provenance receipt (issue [#118](https://github.com/Eliyce/paqad-ai/issues/118)).

  Every verification gate (and quality-ratchet measure) now fans into one append-only ledger at `.paqad/ledger/evidence.jsonl`, and the merge-time backstop projects a per-change receipt from it: an in-toto Statement (v1) with a SLSA-VSA-modelled predicate, wrapped in a DSSE envelope and tamper-evident hash-chained locally (`.paqad/ledger/receipt.dsse.json` + `receipts.jsonl`), plus a CycloneDX-adjacent AI-BOM view (`.paqad/ledger/ai-bom.json`). The anti-"provenance-theater" rule is enforced end to end: every row is graded by evidence strength — deterministic (Tier A) vs LLM-judged (Tier B) vs blocked/inconclusive (Tier C) — so a computed pass is never pooled with a model's say-so. Ledger/receipt failures never block verification.

## 1.11.1

### Patch Changes

- [#129](https://github.com/Eliyce/paqad-ai/pull/129) [`9046543`](https://github.com/Eliyce/paqad-ai/commit/904654309a963f1bad712d89d2e51ae2bafc4100) Thanks [@HLasani](https://github.com/HLasani)! - Fix `onboard` crashing with `EEXIST: file already exists, symlink` when a previous run left a dangling framework symlink (e.g. the npx cache directory it pointed at was garbage-collected). `ensureFrameworkSymlink` now detects the link with `lstat` instead of `existsSync` so dangling symlinks are cleaned up and replaced idempotently.

## 1.11.0

### Minor Changes

- [#127](https://github.com/Eliyce/paqad-ai/pull/127) [`30ba1c5`](https://github.com/Eliyce/paqad-ai/commit/30ba1c5f7e14b42323acddea7d2b7056885c23e2) Thanks [@HLasani](https://github.com/HLasani)! - Make the verification gates bind ([#117](https://github.com/Eliyce/paqad-ai/issues/117)). The existing gate runner now fires
  automatically from a completion hook and a git/CI backstop via a new exported
  `runRepositoryVerification` API, against repository reality, with the judgment
  inputs computed instead of stubbed:
  - C-1: agent-independent verification entry point + non-provider origins
    (`hook-completion`, `git-backstop`, `ci-backstop`); completion (`Stop`) hook,
    git pre-commit hook, and CI backstop script.
  - C-2: `ac-test-mapping`, `implementation-review`, and `spec-review` computed
    from the traceability map, decision store, and spec-review reports; signals
    that need model judgment escalate as inconclusive instead of passing vacuously.
  - C-3: a decision-pause PreToolUse hook that blocks mutating tools while a
    decision packet is unresolved.
  - C-4: scope-drift in the `change-completeness` gate against the derived spec
    boundary, naming the out-of-scope paths.
  - C-5: the live hooks are generated for hook-capable adapters from one
    definition, with a documented per-adapter coverage matrix.
  - C-6: one machine-readable trust verdict, streamed as a `verification-verdict`
    engine event and written to the verification-evidence artifact.

  No new CLI verb. See `docs/verification-enforcement.md` for the enforcement
  boundary and limitations.

## 1.10.1

### Patch Changes

- [#125](https://github.com/Eliyce/paqad-ai/pull/125) [`6708fd6`](https://github.com/Eliyce/paqad-ai/commit/6708fd6c23609efa48f3a1144527c1b44a2630d4) Thanks [@HLasani](https://github.com/HLasani)! - Rewrite the README and marketing site to make it obvious what paqad-ai is and the problem it solves. The new copy leads with the problem, puts a 30-second install up front, and walks through the framework as a guided tour: one setup for every agent, workflows instead of prompts, deterministic verification, security and design workflows, living documentation, token-efficient context, and local-first enterprise features. The docs site introduction and SEO metadata were updated to match.

## 1.10.0

### Minor Changes

- [#116](https://github.com/Eliyce/paqad-ai/pull/116) [`9f3b0ba`](https://github.com/Eliyce/paqad-ai/commit/9f3b0ba18e6e91f1ea1afa47c8d756a20e46ab54) Thanks [@HLasani](https://github.com/HLasani)! - Engine surface buildout for the desktop app (PQD Engine tickets):
  - PQD-92 (seq 24): Author the engine extension surface contract
  - PQD-95 (seq 27): Set up a project profile and `.paqad/` schema versioning baseline
  - PQD-96 (seq 28): Set up structured logging and log-redaction rules across the three runtimes
  - PQD-98 (seq 29): Hot-register a skill in memory at runtime without restarting
  - PQD-99 (seq 30): Subscribe to engine events through a single unified stream
  - PQD-100 (seq 31): Stream slice execution events so consumers can render progress live
  - PQD-101 (seq 32): Stream decision pause events so consumers can pop the packet UI live
  - PQD-102 (seq 33): Accept extracted text from a vision call into the retrieval index
  - PQD-103 (seq 34): Preview the onboarding file tree without writing anything to disk
  - PQD-104 (seq 35): Cancel every long-running engine call from the consumer side
  - PQD-105 (seq 36): Plug a consumer logger into the engine so all engine logs surface in the consumer
  - PQD-106 (seq 37): Report the engine version and the minimum consumer version it supports
  - PQD-107 (seq 38): Surface a stable error taxonomy that consumers can route to UI behaviours
  - PQD-167 (seq 98): Compute the per-turn context budget breakdown for the active model
  - PQD-169 (seq 100): Generate a rolling summary that preserves speaker attribution
  - PQD-171 (seq 102): Rebuild the API conversation deterministically per turn
  - PQD-172 (seq 103): Tag turn priority and protect decision-packet turns from collapse
  - PQD-174 (seq 105): Index attachments into a session-scoped ephemeral RAG collection
  - PQD-194 (seq 125): Emit skill-load-failed and pack-load-failed audit events
  - PQD-331 (seq 266): Index an attached file into the session or project collection
  - PQD-415 (seq 350): Index, retrieve, and destroy a project-scoped CRS collection through the engine
  - PQD-423 (seq 358): Detect the project stack from a folder (AI-first with static fallback)
  - PQD-424 (seq 359): Run onboarding to generate baseline docs and configs (force-overwrite, opt-in entry files, resume checkpoint, policy guard, schema marker, audit event)

## 1.9.0

### Minor Changes

- [#114](https://github.com/Eliyce/paqad-ai/pull/114) [`50f9651`](https://github.com/Eliyce/paqad-ai/commit/50f965179d632b444471459ea756fd7885082ac4) Thanks [@HLasani](https://github.com/HLasani)! - feat: build in small pieces, then reconnect to the whole ([#104](https://github.com/Eliyce/paqad-ai/issues/104))

  Planning now pins the default slice unit to **one acceptance criterion**. On the graduated/full lanes a
  slice that proves no independently-testable criterion is rejected (`SLICE_GRANULARITY_FLOOR`), and a
  slice that bundles several criteria must record why separating them would break the work
  (`SLICE_COMBINE_REASON`, via a new `ExecutionSlice.combine_reason`). The slice executor already takes each
  slice fully through its checks before the next begins; that one-at-a-time ordering is now pinned by test.
  After the slices are built, a new **reconnect check** confirms the assembled pieces fit the _frozen_
  whole-feature spec ([#102](https://github.com/Eliyce/paqad-ai/issues/102)) — every frozen criterion covered and proven, no off-spec or double-owned
  criterion, no unwired cross-slice seam — anchored on the written spec, not the agent's memory. It is a
  real check that fails on an incoherent assembly, structural by default and escalating to an agent
  re-read on the full lane. The fast lane is untouched: trivial work still builds in one step with no
  slicing or reconnect ceremony. Reuses `VerificationCriterion`, `execution_slices`, and the
  plan-vs-actual snapshot — no new acceptance-criterion model and no new slice store.

- [#114](https://github.com/Eliyce/paqad-ai/pull/114) [`50f9651`](https://github.com/Eliyce/paqad-ai/commit/50f965179d632b444471459ea756fd7885082ac4) Thanks [@HLasani](https://github.com/HLasani)! - feat: freeze a machine-checkable feature spec and define a single "done" bar before building ([#102](https://github.com/Eliyce/paqad-ai/issues/102))

  Non-trivial features (graduated/full lanes) now require a frozen spec carrying behaviour,
  acceptance criteria (AC-n, given/when/then, proof_type), and human-confirmed invariants (INV-n),
  validated by the new `feature-spec` schema. A spec freezes only with no open questions, no critical
  spec-review defects, and a confirmed invariant set. "Done" becomes a checkable bar — gates pass, every
  acceptance criterion is proven, and no confirmed problem remains; style/taste never blocks. Mid-build
  goal changes and work-vs-spec contradictions pause via the Decision Pause Contract
  (`spec.change` / `spec.contradiction`). The fast lane is unaffected — trivial work needs no spec.

- [#114](https://github.com/Eliyce/paqad-ai/pull/114) [`50f9651`](https://github.com/Eliyce/paqad-ai/commit/50f965179d632b444471459ea756fd7885082ac4) Thanks [@HLasani](https://github.com/HLasani)! - feat: keep a passing check meaningful — flaky-test detection, quarantine, and trust ([#106](https://github.com/Eliyce/paqad-ai/issues/106))

- [#114](https://github.com/Eliyce/paqad-ai/pull/114) [`50f9651`](https://github.com/Eliyce/paqad-ai/commit/50f965179d632b444471459ea756fd7885082ac4) Thanks [@HLasani](https://github.com/HLasani)! - feat: add a mutation-testing verification gate that plants mutants in the changed code, reports the kill rate and surviving mutants (file/line/operator), and selects the mature per-language tool — marking weak-tooled languages lower-confidence — with full tree-clean safety and per-module score roll-up ([#105](https://github.com/Eliyce/paqad-ai/issues/105))

- [#114](https://github.com/Eliyce/paqad-ai/pull/114) [`50f9651`](https://github.com/Eliyce/paqad-ai/commit/50f965179d632b444471459ea756fd7885082ac4) Thanks [@HLasani](https://github.com/HLasani)! - feat: never fix a problem without first proving it exists ([#103](https://github.com/Eliyce/paqad-ai/issues/103))

  A behaviour-affecting fix now follows a four-step protocol — prove broken, fix, prove fixed, prove
  nothing else broke — and the proof is kept as a durable regression guard so the same defect cannot
  silently return. The proof is validated as genuine (re-run against the unfixed tree must fail);
  trivially-passing proofs are rejected. After the fix, the full check set runs and any newly-failing
  previously-passing check rejects the fix, reusing the existing test-output delta projection — no parallel
  result store. Problems that genuinely cannot be auto-checked (timing/appearance) open a single
  `fix.proof_method` Decision Pause, asked once and reused by kind. Proof-first is skipped only for changes
  that cannot affect behaviour (comments, blank lines, docs); when in doubt, the change is treated as
  behaviour-affecting, so the fast lane stays light for cosmetic edits.

- [#114](https://github.com/Eliyce/paqad-ai/pull/114) [`50f9651`](https://github.com/Eliyce/paqad-ai/commit/50f965179d632b444471459ea756fd7885082ac4) Thanks [@HLasani](https://github.com/HLasani)! - feat: quality ratchet — record four quality measures at today's real level and only ever allow equal-or-better ([#110](https://github.com/Eliyce/paqad-ai/issues/110))

  Captures tangledness, dead/unused code, risky patterns, and strictness into
  `.paqad/quality-baseline.json` (per module + project), then a verification gate
  refuses any change that worsens a measure — the recorded level only tightens.
  Dead code is consumed from [#109](https://github.com/Eliyce/paqad-ai/issues/109)'s reachability output (one solver, two uses);
  the baseline starts from reality so day one is no clean-up; a legitimate
  regression opens a reused-by-kind `quality.ratchet_exception` Decision Pause.
  The fast lane isn't blocked by measure noise but still cannot loosen the
  baseline.

- [#114](https://github.com/Eliyce/paqad-ai/pull/114) [`50f9651`](https://github.com/Eliyce/paqad-ai/commit/50f965179d632b444471459ea756fd7885082ac4) Thanks [@HLasani](https://github.com/HLasani)! - feat: bounded, quiet build-check-fix loop — wrap the single verification pass in lane-scaled rounds with futility detection, keep the round record internal, and emit exactly one honest "stuck" report via the `stop` escalation at the cap ([#108](https://github.com/Eliyce/paqad-ai/issues/108))

- [#114](https://github.com/Eliyce/paqad-ai/pull/114) [`50f9651`](https://github.com/Eliyce/paqad-ai/commit/50f965179d632b444471459ea756fd7885082ac4) Thanks [@HLasani](https://github.com/HLasani)! - feat: make sure everything promised got built and nothing extra crept in — bidirectional traceability ([#109](https://github.com/Eliyce/paqad-ai/issues/109))

  Rebuilds a two-way promise ↔ code ↔ test map from reality each run, joining the existing compliance forward link (spec→test), the module map, the import graph, and verification-evidence `ac_id`. Flags promises with no proving check (`TR-UNTESTED-PROMISE`) and code that answers to no promise and that nothing-with-a-promise uses (`TR-CODE-ORPHAN`, decided by reachability over the import graph — not by a label). Shared groundwork passes by _use_; a "this is fine" comment cannot suppress a truly-dead flag. Lane-gated (fast = change-set subset; graduated/full = full build) and written to `.paqad/traceability/map.json`.

- [#114](https://github.com/Eliyce/paqad-ai/pull/114) [`50f9651`](https://github.com/Eliyce/paqad-ai/commit/50f965179d632b444471459ea756fd7885082ac4) Thanks [@HLasani](https://github.com/HLasani)! - feat: sort every finding into four piles before acting — only confirmed, demonstrable problems drive a code change; unclear-spec routes to the spec, false-alarm/taste are recorded, ambiguous opens a `finding.triage` Decision Pause reused by kind ([#107](https://github.com/Eliyce/paqad-ai/issues/107))

## 1.8.1

### Patch Changes

- [#100](https://github.com/Eliyce/paqad-ai/pull/100) [`fda3dd0`](https://github.com/Eliyce/paqad-ai/commit/fda3dd0e64091dd81e20e0ad4c6649e7541369c6) Thanks [@HLasani](https://github.com/HLasani)! - fix([#72](https://github.com/Eliyce/paqad-ai/issues/72)): make `refresh` opt-in and stop shipping generic design-token defaults
  - `paqad-ai refresh` with no target flag is now a status-only no-op. Stack refresh and module-map reconciliation are no longer implicitly on — every target (`--stack`, `--context`, `--providers`, `--rules`, `--reconcile-module-map`) must be requested explicitly, so `refresh` never materializes files the user did not ask for.
  - The design-token seed no longer writes a generic teal/amber brand. It seeds a clearly-marked, neutral placeholder scaffold, and the documentation workflow refuses to derive `design-system/*.md` and theme exports from that placeholder (skipping with a clear "fill in your real tokens" message) instead of generating authoritative-looking docs for a design system that does not exist.

## 1.8.0

### Minor Changes

- [#93](https://github.com/Eliyce/paqad-ai/pull/93) [`752cae8`](https://github.com/Eliyce/paqad-ai/commit/752cae87341b909ed12635db8f07dfc07f5036c5) Thanks [@HLasani](https://github.com/HLasani)! - Overhaul the rule packs shipped into onboarded projects, and add
  `paqad-ai refresh --rules` to regenerate them (issue [#94](https://github.com/Eliyce/paqad-ai/issues/94)).

  **Why.** An audit of every rule under `runtime/**/rules/**` found four problems:
  factually wrong / hallucinated rules (the Laravel `boost.md` invented a "Boost
  module system" that does not exist; two Axum/serde claims in `rust-web` security
  were wrong), rules that duplicated the per-project `module-map.yml`, framework
  plumbing leaking into projects (`.paqad/` paths, phases, lanes, cache metrics),
  and large amounts of non-actionable platitude ("keep X aligned; document when it
  changes").

  **What changed.**
  - **Correctness.** `boost.md` now describes the real Laravel Boost MCP server
    (tools, guidelines, docs API) instead of a fabricated module system. The two
    wrong `rust-web/security` lines are fixed (auth via a `tower` layer / a
    `FromRequestParts` extractor; `#[serde(skip)]` for never-serialized fields).
  - **Every stack rewritten.** All stack and capability rule packs (laravel,
    react, vue, flutter, go-web, rust-web, angular, astro, django, dotnet,
    express, fastapi, flask, nestjs, nextjs, rails, spring-boot, svelte,
    kotlin-android, and the framework/meta-framework capabilities) were rewritten
    to be concrete, framework-accurate, and checkable against a diff. Version-stale
    APIs were corrected (e.g. Tailwind v4 `@theme`/`@source`, Inertia v2
    `optional`/`defer`).
  - **No more `module-map.yml` duplication.** `architecture.md`/`modules.md` now
    point to `docs/instructions/rules/module-map.yml` as the source of truth for
    module ownership instead of restating generic boundary advice.
  - **No framework footprint.** Base and `_shared` rules no longer reference
    `.paqad/`, phases, lanes, handoff, or cache/context metrics; a project can
    delete `.paqad/` with no dangling rule references.
  - **New command.** `paqad-ai refresh --rules` re-resolves the framework rule
    packs for the project's saved stack and rewrites `docs/instructions/rules/`.
    Without `--force` it reports the plan (what would be deleted/written) and makes
    no changes; with `--force` it deletes the previously generated rules and
    rewrites them, preserving the project-owned `module-map.yml` and
    `rule-script-map.yml`.
  - **Guards.** A new `tests/unit/content/rule-quality.test.ts` rejects rule files
    that contain workflow markers (`## Trigger`, `### Step`, `run_id`) or `.paqad/`
    references, so these regressions are blocked. `runtime/rules-authoring.md`
    documents the contract.

  Note: the `design-test`/`design-retest`/`pentest` workflow specs still live under
  `rules/` (the onboarding contract and tests depend on them as generated files);
  relocating them out of the copied rule set is tracked as follow-up and they are
  allowlisted in the guard for now.

### Patch Changes

- [#93](https://github.com/Eliyce/paqad-ai/pull/93) [`752cae8`](https://github.com/Eliyce/paqad-ai/commit/752cae87341b909ed12635db8f07dfc07f5036c5) Thanks [@HLasani](https://github.com/HLasani)! - Relocate the design-system source of truth and label generated outputs (issue
  [#92](https://github.com/Eliyce/paqad-ai/issues/92)). The canonical, hand-edited `design-tokens.json` now lives at
  `docs/instructions/design-system/design-tokens.json` — co-located with the
  Markdown it produces — instead of under `docs/instructions/architecture/`. Each
  generated file (`tokens.md`, `components.md`, `motion.md`, `accessibility.md`,
  `responsive.md`, `patterns.md`) now carries a `GENERATED … do not edit` banner
  pointing back at the source, and the seeded JSON carries a `$comment` declaring
  it the canonical source. This makes it obvious on disk which file to edit and
  which are outputs.

  **`paqad refresh` no longer handles the design system at all.** The
  `--design-system` flag is removed, and a bare `refresh` no longer seeds or
  regenerates design-system docs/theme exports. The design system (the canonical
  `design-tokens.json` and the Markdown generated from it) is owned solely by the
  documentation workflow (`create documentation`). User-facing guidance that
  pointed to `paqad refresh --design-system` (README, the design-system rule, the
  dashboard hint) has been removed accordingly.

  Note: no automatic migration of already-onboarded projects. A project whose
  tokens file is still under `architecture/` should move it to `design-system/`
  manually.

## 1.7.0

### Minor Changes

- [#90](https://github.com/Eliyce/paqad-ai/pull/90) [`71711f0`](https://github.com/Eliyce/paqad-ai/commit/71711f0e6574654cf9826b03a5dcfb24ee3d5aaa) Thanks [@HLasani](https://github.com/HLasani)! - Add **rules-as-scripts** (issue [#89](https://github.com/Eliyce/paqad-ai/issues/89)): turn the prose rules under
  `docs/instructions/rules/**` into deterministic, per-project verification
  scripts that run as a sub-step of `feature-development.checks`, so rule
  adherence no longer depends solely on the model remembering them.

  All prompt-driven — no new user-facing CLI commands:
  - `analyze rules` (`rule-analyzer`) — embeds stable `<!-- @rule RL-<hash> -->`
    markers, classifies each rule `deterministic` / `heuristic` / `unverifiable`,
    detects rules already enforced by ESLint/TS/etc., flags conflicts, and writes
    a reviewable `docs/instructions/rules/rule-script-map.yml`.
  - `generate rule scripts` (`rule-script-generator`) — authors one `.mjs` per
    rule plus synthetic `__fixtures__/{pass,fail}`. A script that misclassifies
    its own fixtures is rejected via the Decision Pause Contract — never
    registered. Strict from generation; per-kind over-flag guard.
  - `feature-development.checks.rule_compliance` runs the registered scripts
    diff-scoped, hash-cached. `deterministic` findings block under `mode: strict`;
    `heuristic` findings route to review and never block. Missing declared
    binaries are reported and skipped, never crash the stage.
  - `add rule` / `edit rule` / `remove rule` / `mark rule as unverifiable`
    (`rule-editor`) — per-rule cascade with stable IDs; no global rebuild.
  - `rule-script-reconciler` surfaces `RS-*` drift (rules edited without regen,
    manual map edits, failing fixtures) at planning entry.
  - New dashboard **Rule Compliance** card; onboarding plants the `analyze rules`
    prompt. Engine exposed as the `paqad-ai/rule-scripts` subpath export.
  - `finding-normalizer` promoted from the security capability to base so its
    cross-capability vocabulary (`PEN-`/`DT-`/`MD-`/`RS-`) is no longer nested
    under one capability.

  Provider-neutral: the same prompt sequence and skills produce identical
  artifacts across every supported adapter.

## 1.6.1

### Patch Changes

- [#87](https://github.com/Eliyce/paqad-ai/pull/87) [`a5e350b`](https://github.com/Eliyce/paqad-ai/commit/a5e350b0d25b4cec7415d78467f624b4e664a1ca) Thanks [@HLasani](https://github.com/HLasani)! - Fix `design test` workflow scripts that failed on every onboarded project:
  - `runtime/scripts/design/scan-tokens.sh` resolved its helper scanner via a
    CWD-relative path, so Step 2 always exited 2 with
    `error: skill scanner missing` when run from anywhere other than the
    runtime root. Now resolves the helper relative to the script's own
    location.
  - `runtime/scripts/design/coverage.sh` aborted under macOS's stock Bash 3.2
    (`set -u` + empty-array expansion) whenever the components directory or a
    component's matching tests were empty — the common first-run case. Guarded
    the three vulnerable `"${arr[@]}"` expansions with the
    `${arr[@]+"${arr[@]}"}` idiom.

  Closes [#86](https://github.com/Eliyce/paqad-ai/issues/86).

## 1.6.0

### Minor Changes

- [#84](https://github.com/Eliyce/paqad-ai/pull/84) [`82d6c45`](https://github.com/Eliyce/paqad-ai/commit/82d6c457b0768e647cddb932547101e4fe45c4d2) Thanks [@HLasani](https://github.com/HLasani)! - feat([#76](https://github.com/Eliyce/paqad-ai/issues/76)): design-test workflow — UI audit against the project's design-system contract

  Adds a heavyweight design-test workflow that mirrors pentest but grades the running UI against `docs/instructions/design-system/*`. Intent-routed (no slash command), resumable, 9 skills + readiness gate, 7 framework-owned runners under `runtime/scripts/design/`, Playwright live phase, `DT-XXXX` finding ids with stable `token | component | state | a11y | responsive | motion | copy | performance | documentation-drift` categories. Companion `design-retest` workflow preserves IDs across re-runs.

  **Workflow**
  - New workflow rules: `runtime/capabilities/coding/rules/design-test.md` + `design-retest.md`.
  - 11 design-test routing triggers at priority 235; 4 design-retest triggers at 245.
  - `feature-development.yaml` splices design-system reads + per-stage instructions through planning → specification → development → review → checks → documentation_sync (schema-conformant via `merge_mode: append`).

  **Skills (the LLM-reasoning layer)**
  - `design-system-coverage` (readiness gate, mirrors `stride-threat-model`), `token-conformance-review`, `component-conformance-review`, `state-coverage-review`, `accessibility-review` (WCAG 2.2 A/AA), `responsive-review`, `motion-review`, `copy-and-ia-review`, `design-system-sync`.
  - **Hard-coded design values** (hex literals, raw `px`/`rem`, ad-hoc font stacks where a token exists) default to **high severity** — first-class findings, not a stylistic preference.

  **Deterministic scripts (the complement to the LLM layer)**

  Per the [agentskills.io](https://agentskills.io) contract: 25 small, focused scripts do the mechanical work so the agent doesn't re-derive it on every run. Each script has `--help`, structured stdout, stderr diagnostics, and meaningful exit codes (0 ok, 1 finding, 2 usage).
  - design-system-coverage: `count-clauses`, `derive-tier`, `gap-report`
  - token-conformance-review: `parse-tokens`, `normalize-color`, `match-leak-to-token`
  - component-conformance-review: `derive-inventory`, `parse-components-md`, `diff-inventories`
  - state-coverage-review: `extract-source-states`, `extract-tested-states`, `cross-reference-states`
  - accessibility-review: `static-a11y-scan`, `parse-axe-violations`, `map-axe-to-wcag`
  - responsive-review: `extract-breakpoints`, `find-horizontal-scroll`, `find-touch-target-violations`
  - motion-review: `scan-animations`, `parse-motion-budget`, `find-reduced-motion-violations`
  - copy-and-ia-review: `extract-user-strings`, `check-action-verbs`, `check-terminology`
  - design-system-sync: `detect-token-additions`, `detect-component-additions`, `propose-tokens-diff`, `propose-components-diff`

  **Framework runners (zero project footprint)**

  `runtime/scripts/design/{scan-tokens, scan-overrides, enumerate-surface, axe-static, coverage, runtime-checks.ts, retest}` — all ship inside paqad-ai; outputs land in the project at `docs/design-test/*` and `.paqad/design-test/runs/*` as work products. Diverges from pentest's project-seeded runner model intentionally; the divergence is documented in the workflow rule.

  **Finding normalizer**

  `DT-` code prefix, design-test category vocabulary, `blocker | nit` severities + `accepted | waived | still-open | needs-manual-verification` statuses.

  **Tests**

  ~200 fixture-driven test cases under `tests/unit/skills/` + `tests/fixtures/design-skills/<skill>/`. The `coverage-completeness` meta-test enforces that every script is referenced by basename in its spec, passes `bash -n`, and that every backticked path in each `SKILL.md` Resources section exists on disk.

  **Skill-authoring rule**

  `docs/instructions/rules/_shared/skill-authoring.md` captures the contract for future skills — anatomy, frontmatter, the deterministic-vs-judgment boundary, the script interface contract, portability workarounds (no `mapfile`, no `\b` in awk, BSD grep alternation quirk, missing-trailing-newline guard), and the testing rules. Auto-loaded by the framework entry, so future skills inherit the contract without being told.

## 1.5.0

### Minor Changes

- [#82](https://github.com/Eliyce/paqad-ai/pull/82) [`f330595`](https://github.com/Eliyce/paqad-ai/commit/f330595d38c5e66afc54443daefe9e4f97a7ea68) Thanks [@HLasani](https://github.com/HLasani)! - Living module lifecycle: prospective decisions, retrospective reconciliation, test-driven health, dashboard drift checks (closes [#80](https://github.com/Eliyce/paqad-ai/issues/80))

## 1.4.0

### Minor Changes

- [#75](https://github.com/Eliyce/paqad-ai/pull/75) [`283d973`](https://github.com/Eliyce/paqad-ai/commit/283d9736621e7571013a377408a8ec6416b54df9) Thanks [@HLasani](https://github.com/HLasani)! - Gate every agent turn on the entry-file load, not just code-mutating tool
  calls. Onboarded projects previously could answer read-only prompts (Q&A,
  "what is this project", explanations) without loading `CLAUDE.md`,
  `.paqad/framework-path.txt`, or `docs/instructions/{rules,stack,design-system}`
  — the framework's rules and Decision Pause Contract silently never entered
  context.

  The Claude Code adapter now installs a `UserPromptSubmit` hook
  (`runtime/hooks/agent-entry-prompt-gate.sh`) alongside the existing
  `PreToolUse` hook. Both gates share sentinel-freshness logic via
  `runtime/hooks/lib/agent-entry-sentinel.sh` so they cannot drift.

  Soft mode (default): the hook prints a high-priority reminder on stdout; Claude
  Code injects it into the model context before the turn is planned. Hard mode
  (`PAQAD_AGENT_ENTRY_MODE=hard`): the hook exits non-zero and blocks the turn
  until the sentinel is written.

  Re-running onboarding / `paqad upgrade` refreshes the wiring in
  `.claude/settings.json` idempotently. Resolves Eliyce/paqad-ai#74.

## 1.3.0

### Minor Changes

- [#67](https://github.com/Eliyce/paqad-ai/pull/67) [`c4312aa`](https://github.com/Eliyce/paqad-ai/commit/c4312aab1366c6c25138e6de38cff935c862ccb1) Thanks [@HLasani](https://github.com/HLasani)! - Add `paqad-ai dashboard` and `paqad-ai status` — the living single-pane health overview for an onboarded paqad project.

  `paqad-ai dashboard` starts a local web server (port 5372, auto-incrementing) on the same bundle as `paqad-ai graph`. The graph view is now one section inside the dashboard, opened via the architecture card; the existing `paqad-ai graph` command is unchanged and is still a direct shortcut to the graph route. Sections rendered in Phase 1: project profile, rules, workflows, decisions (living), module health (living), module docs, architecture, design system, stack, registries, tools, tech-debt, stack drift, framework version, RAG status, and — when present — pentest and session continuity. Each card shows a score badge, a one-line state-derived summary, a `?` helper popover, and up to three compact metrics. Score is existence + freshness only (file present + last-modified ≤ 30d = 100%, decays linearly to 0 at the 180d cliff); no content-quality heuristics in Phase 1. The summary band surfaces up to five "Needs your attention" items, critical-first. The card border pulses (200ms accent) when SSE re-fetch updates a section — the one allowed animation.

  `paqad-ai status` is the same `buildReport()` pipeline, but one-shot — no server, no long-running process. Defaults to a deterministic Markdown rendering for humans / PR descriptions; `--format json` emits the stable `schemaVersion: 1` contract for agent prompts.

  Zero install footprint: the bundle ships inside the package (mirroring the existing `runtime/graph-ui/` pattern), no new files are written into the user's project, scoring is computed on the fly, and no new MCP server or background process is introduced. Reuses every `--color-mod-*` design token already present in `graph-ui/src/index.css` — no new design tokens.

  Closes [#64](https://github.com/Eliyce/paqad-ai/issues/64).

### Patch Changes

- [#71](https://github.com/Eliyce/paqad-ai/pull/71) [`c530fa3`](https://github.com/Eliyce/paqad-ai/commit/c530fa34d032f7f454f49386bc66987e32cb726a) Thanks [@HLasani](https://github.com/HLasani)! - Stop leaking absolute install paths into committed onboarding artifacts ([#69](https://github.com/Eliyce/paqad-ai/issues/69)). The hooks manifest (`.claude/settings.hooks.json`, `.codex/hooks.json`, `.gemini/hooks.json`, etc.) now stores only the package-relative `source` and resolves the hook script at runtime, instead of baking in `/opt/homebrew/lib/node_modules/paqad-ai/...` or `~/.npm/_npx/<hash>/...` from the onboarding user's machine. A teammate cloning the repo (different OS user, different package manager, Mac vs. Windows) can now run Paqad without every hook 404'ing, and usernames/machine layout no longer end up in source control. Adds a portability test that scans all generated config across every adapter × fixture combination for leaked absolute paths.

## 1.2.1

### Patch Changes

- [#65](https://github.com/Eliyce/paqad-ai/pull/65) [`f398b00`](https://github.com/Eliyce/paqad-ai/commit/f398b00ced1d676a5e35452a3da7d143431569a0) Thanks [@HLasani](https://github.com/HLasani)! - Fix `paqad-ai onboard` hanging on the RAG "No, skip" path at the end of the full interactive prompt chain.

  The orchestrator previously interleaved the RAG inquirer prompt with file writes: `resolveRagSelection()` ran early, and `writeDetectionReport` / `writeFrameworkMetadata` / `writeOnboardingManifest` / `writeDecisionPauseContractDocument` / `compileRules` / `initializeModuleHealth` / `classifier-config.json` / `next-steps.md` all ran _after_ it. When inquirer left a stuck readline handle on Node's event loop — observed reliably with the full prompt chain on the No-skip branch — every post-RAG write was silently dropped. Users were left with an incomplete `.paqad/**` and no `ONBOARDING COMPLETE` banner.

  Onboarding is now two-phase. Phase 1 writes every core `.paqad/**` artifact and `CLAUDE.md`-equivalents with no inquirer prompts in the path. The new `onPhase1Complete` callback fires only after the onboarding manifest is on disk, so the success banner prints before phase 2 begins. Phase 2 owns the RAG opt-in (prompt → optional index build → idempotent `writeProjectProfile` update). If phase 2 prompts, hangs, fails, or is interrupted, every phase 1 artifact is already durable on disk.

  Adds three orchestrator invariant unit tests that pin the new contract (`onPhase1Complete` fires after all core artifacts exist; a thrown `RagService.configureAndBuild` does not drop core writes; a thrown `resolveRagSelection` does not drop core writes) and a PTY-driven E2E (gated on the system `expect(1)` binary, skipped on platforms without it) that drives the real built CLI through the full interactive Laravel prompt chain, picks "No, skip" on RAG, and asserts the complete `.paqad/**` artifact set on disk.

  Closes [#62](https://github.com/Eliyce/paqad-ai/issues/62).

## 1.2.0

### Minor Changes

- [#60](https://github.com/Eliyce/paqad-ai/pull/60) [`2e35581`](https://github.com/Eliyce/paqad-ai/commit/2e355817f14792fc51b7beada9001f96eaac4b13) Thanks [@HLasani](https://github.com/HLasani)! - **[#37](https://github.com/Eliyce/paqad-ai/issues/37) — Decision Pause Contract: ship the full resolution flow to every provider via one managed external doc**
  - Onboarding now writes a canonical `.paqad/decision-pause-contract.md` (rule, categories sourced from `DECISION_CATEGORIES`, four-step resolution flow, per-adapter UI table, file-wait fallback) — re-runs are byte-identical when nothing changed.
  - Every provider entry file (`CLAUDE.md`, `AGENTS.md`, `.cursor/rules/…`, `.windsurf/rules/…`, `GEMINI.md`, `.junie/AGENTS.md`, `ANTIGRAVITY.md`, `.github/copilot-instructions.md`, `.continue/…`, `.aider.conf.yml`) now renders a thin pointer + a one-sentence per-adapter UI note (Claude Code → `AskUserQuestion`, Aider → `/ask`, etc.) from the new `decision-pause-ui-shim`.
  - `paqad refresh --providers` re-renders entry files for adapters whose config exists on disk and rewrites the managed doc; it intentionally does not silently onboard new providers.
  - Health check now compares each entry against its adapter's expected rendering and warns when the managed doc is missing, with a remediation hint pointing at `paqad refresh --providers`.

  **[#42](https://github.com/Eliyce/paqad-ai/issues/42) — `ticket_intake` + `delivery` bookend stages with priors-first decision elicitation**
  - New stage order: `ticket_intake → planning → specification → development → review → checks → documentation_sync → delivery`. Both bookends are framework-owned and project-overridable via the existing `merge_mode: append` mechanism; the JSON schema rejects unknown keys with `additionalProperties: false`.
  - New optional top-level `conventions:` block on the project profile covering `ticket / intake_decisions / branch / commit / pr`. `DEFAULT_CONVENTIONS` is the runtime source of truth; `resolveConventions` shallow-merges project overrides per section so every field is populated for downstream consumers.
  - `mcp.servers[]` gains an optional `kind` discriminator (`jira | linear | github-issues | generic`); existing servers without `kind` keep validating.
  - Four new `DECISION_CATEGORIES`: `intake.requirement`, `intake.confirm_auto_resolution`, `intake.write_back`, `delivery.open_pr`. All ride the existing pending → resolved lifecycle, audit log, and TTL machinery.
  - `findIntakePriorMatch` is the dedicated priors-first entrypoint for intake; it computes the fingerprint and reuses the existing `DecisionStore.findReusableDecision` machinery, which already emits `decision-reused` audit events on every hit.
  - New batched-confirm primitive (`BatchedConfirmRequest`, `applyBatchedAnswer`, `renderBatchedRow`) backs `intake.confirm_auto_resolution`. Single-packet flow remains the default for every other category.
  - New `src/delivery/` modules: `templates.ts` renders branch / commit / pr_title / pr_body from the conventions block + inputs (slugify, conventional type mapping, `{placeholder}` substitution); `host.ts` detects the delivery host (GitHub today, GitLab / Bitbucket recognised); `runner.ts` sequences `git checkout -b → git commit → git push → gh pr create` through a dependency-injected `DeliveryShell` so unit tests don't touch a real remote. Every failure short-circuits with an actionable remediation hint — no silent local-only fallback.
  - Default PR body template at `runtime/templates/pr-body.md.hbs`; projects can override with `.paqad/templates/pr-body.md`.
  - Module docs: `docs/modules/decision-pause-contract/managed-doc-architecture.md` and `docs/modules/feature-development-workflow/ticket-intake-and-delivery.md`.

## 1.1.0

### Minor Changes

- [#58](https://github.com/Eliyce/paqad-ai/pull/58) [`195ae7d`](https://github.com/Eliyce/paqad-ai/commit/195ae7dbca635305e8a3aaff9fb08f0af72e9cbc) Thanks [@HLasani](https://github.com/HLasani)! - Add a harness-enforced agent-entry gate so onboarded Claude Code projects can't silently bypass `CLAUDE.md` ([#34](https://github.com/Eliyce/paqad-ai/issues/34)). Onboarding now writes `.claude/settings.json` with two hooks:
  - `PreToolUse` on `Edit|Write|NotebookEdit` runs `runtime/hooks/agent-entry-gate.sh`, which blocks the call with exit code 2 unless `.paqad/.agent-entry-loaded` exists and is newer than `CLAUDE.md`, `.paqad/framework-path.txt`, and everything under `docs/instructions/`.
  - `SessionStart` runs `runtime/hooks/agent-entry-session-start.sh`, which deletes the sentinel so every new session starts ungated.

  The CLAUDE.md template now instructs the agent to write the sentinel after loading the framework entry, and to re-load when the gate invalidates it. Existing settings.json keys and pre-existing hook entries are preserved on merge, and re-running onboarding is idempotent (no duplicate gate entries). Read-only tools (Read, Grep, Glob, status-only Bash) remain available pre-gate so the agent can satisfy it. AGENTS.md and other providers can re-use the same scripts in follow-ups via `PAQAD_ENTRY_FILE`.

### Patch Changes

- [#58](https://github.com/Eliyce/paqad-ai/pull/58) [`195ae7d`](https://github.com/Eliyce/paqad-ai/commit/195ae7dbca635305e8a3aaff9fb08f0af72e9cbc) Thanks [@HLasani](https://github.com/HLasani)! - Make onboarding re-runs idempotent ([#27](https://github.com/Eliyce/paqad-ai/issues/27)): when `.paqad/detection-report.json`, `.paqad/onboarding-manifest.json`, and `.paqad/framework-version.txt` would otherwise be byte-identical apart from their embedded timestamp, the writer now reuses the existing timestamp instead of stamping a fresh one. A no-op re-run produces zero diff; any real change still bumps the timestamp. Fixes the Windows-CI `is idempotent across repeated onboarding runs` failure (timing luck was hiding the same bug on macOS/Linux).

- [#58](https://github.com/Eliyce/paqad-ai/pull/58) [`195ae7d`](https://github.com/Eliyce/paqad-ai/commit/195ae7dbca635305e8a3aaff9fb08f0af72e9cbc) Thanks [@HLasani](https://github.com/HLasani)! - `paqad-ai refresh` now self-heals when `docs/instructions/architecture/design-tokens.json` is missing ([#56](https://github.com/Eliyce/paqad-ai/issues/56)). The design-system step seeds default tokens via the existing idempotent `DesignTokenService.seed()` before generating docs and theme exports, so `--stack` and `--context` sub-refreshes no longer get aborted by an unhandled `ENOENT`. `DesignTokenService.load()` now translates a missing file into a typed `DesignTokensMissingError` with an actionable message; invalid (but present) files still surface the existing validation error.

- [#58](https://github.com/Eliyce/paqad-ai/pull/58) [`195ae7d`](https://github.com/Eliyce/paqad-ai/commit/195ae7dbca635305e8a3aaff9fb08f0af72e9cbc) Thanks [@HLasani](https://github.com/HLasani)! - Stop emitting the hardcoded `Categories:` block in provider entry files ([#54](https://github.com/Eliyce/paqad-ai/issues/54)). `buildDecisionPauseContractSection()` now renders just the Decision Pause Contract paragraph — no `Categories:` heading, no fixed five-item bullet list. `extractDecisionPauseContractSection` still parses entry files that previously contained the block (back-compat), and the existing drift health check flags the legacy block so re-running onboarding / refresh strips it from already-onboarded projects.

- [#58](https://github.com/Eliyce/paqad-ai/pull/58) [`195ae7d`](https://github.com/Eliyce/paqad-ai/commit/195ae7dbca635305e8a3aaff9fb08f0af72e9cbc) Thanks [@HLasani](https://github.com/HLasani)! - Cross-platform output consistency: normalize path strings to forward slashes at more production output boundaries — DocumentationWorkflow generated/skipped arrays and handover_path, onboarding orchestrator manifest writes and return values, `saveObligationIndex` return, registry-generator source_paths (both native-module and signal-extracted), and the project-question phase write target. Fix `slugifySpec` to split on both `/` and `\\` so spec-indexed compliance paths derive correctly on Windows. Rewrite `sanitizePersistedPath` to avoid relying on `process.cwd()` for relative inputs. Drops the Windows CI failure count from 15 → 11 test files ([#41](https://github.com/Eliyce/paqad-ai/issues/41)).

## 1.0.7

### Patch Changes

- [#55](https://github.com/Eliyce/paqad-ai/pull/55) [`d47cf96`](https://github.com/Eliyce/paqad-ai/commit/d47cf964d0c661c8369e7f69c374df02ef84a8c9) Thanks [@HLasani](https://github.com/HLasani)! - Cross-platform output consistency: normalize path strings to forward slashes at more production output boundaries — DocumentationWorkflow generated/skipped arrays and handover_path, onboarding orchestrator manifest writes and return values, `saveObligationIndex` return, registry-generator source_paths (both native-module and signal-extracted), and the project-question phase write target. Fix `slugifySpec` to split on both `/` and `\\` so spec-indexed compliance paths derive correctly on Windows. Rewrite `sanitizePersistedPath` to avoid relying on `process.cwd()` for relative inputs. Drops the Windows CI failure count from 15 → 11 test files ([#41](https://github.com/Eliyce/paqad-ai/issues/41)).

## 1.0.6

### Patch Changes

- [#38](https://github.com/Eliyce/paqad-ai/pull/38) [`c7aac12`](https://github.com/Eliyce/paqad-ai/commit/c7aac120bc503cf5122a8205c28c54506c96730f) Thanks [@HLasani](https://github.com/HLasani)! - Internal code-quality cleanup: remove 13 dead-store assignments flagged by `@eslint/js` v10's `no-useless-assignment` rule, and attach the original error as `cause` when wrapping decision-pause write failures so callers can inspect the underlying I/O error via `error.cause`.

- [#39](https://github.com/Eliyce/paqad-ai/pull/39) [`26bde79`](https://github.com/Eliyce/paqad-ai/commit/26bde79c651b7809de65469a5ac8fb23c9e20675) Thanks [@HLasani](https://github.com/HLasani)! - Upgrade TypeScript from 5.9.x to 6.0.x. Adds `ignoreDeprecations: "6.0"` to `tsconfig.json` to silence the `baseUrl`-deprecation warning emitted by `tsup`'s internal dts build pipeline (TS 7.0 will remove `baseUrl` entirely; tsup needs to drop its internal use before then).

## 1.0.5

### Patch Changes

- [#35](https://github.com/Eliyce/paqad-ai/pull/35) [`c8f7f03`](https://github.com/Eliyce/paqad-ai/commit/c8f7f03c60f4149579b4f3fb1c3c89be21c77811) Thanks [@HLasani](https://github.com/HLasani)! - Normalize generated path strings to forward slashes at more production output boundaries for cross-platform consistency ([#30](https://github.com/Eliyce/paqad-ai/issues/30), [#33](https://github.com/Eliyce/paqad-ai/issues/33)). Retry `runScript` once on transient bash-subprocess failures ([#25](https://github.com/Eliyce/paqad-ai/issues/25)). Skip Windows-incompatible tests in CI excludes and align timeouts ([#28](https://github.com/Eliyce/paqad-ai/issues/28)).

## 1.0.4

### Patch Changes

- [#21](https://github.com/Eliyce/paqad-ai/pull/21) [`8bc2642`](https://github.com/Eliyce/paqad-ai/commit/8bc2642c3af5f0af5dfc569507544c092b891503) Thanks [@HLasani](https://github.com/HLasani)! - Read `VERSION` constant dynamically from `package.json` at module load instead of hardcoding it. Future releases no longer need a manual `src/index.ts` edit to keep the exported constant in sync with the published version. Closes [#18](https://github.com/Eliyce/paqad-ai/issues/18).

## 1.0.3

### Patch Changes

- [#15](https://github.com/Eliyce/paqad-ai/pull/15) [`99b1e5b`](https://github.com/Eliyce/paqad-ai/commit/99b1e5b18f42634006f88e16c7eb2fc7091d3f43) Thanks [@HLasani](https://github.com/HLasani)! - First automated release via Changesets + GitHub Actions. No runtime change — this release exists only to validate the new publish pipeline (CI gating, version PR, npm provenance).

All notable changes to this project will be documented in this file. See [Changesets](https://github.com/changesets/changesets) for commit guidelines.
