Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
bump: major
---

### Removed

- The prerequisite resolver (`skills/setup/scripts/resolve-prerequisites.mjs`) no longer reads a repo-root `.work-item-tracker.json`. The tracker need is present only when `docs/conventions/work-items.yaml` sets a `tracker` mapping; otherwise it is absent, and routines that need the tracker resolve `unsupported`. The absent detail names `/work-items:setup apply` as the fix, and names the JSON file when one is present.

### Changed

- The prerequisite-resolution reference and the backlog-readiness, duplicate-detection, issue-triage and pr-queue-tending routines name only the YAML binding.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
bump: patch
---

### Changed

- The audit skill's session-mode reference reads role labels only from the `tracker` mapping of `docs/conventions/work-items.yaml`, matching the work-items seam, which no longer reads a repo-root `.work-item-tracker.json`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
bump: major
---

### Removed

- The babysit scripts no longer read role labels from a repo-root `.work-item-tracker.json`. `babysit_tracker_binding.py` reads only the `tracker` mapping of `docs/conventions/work-items.yaml`; `LEGACY_PATH` is gone and `PATHS` holds only that file, so the merge-skip cache key no longer covers the JSON file. A repository bound only by the JSON file gets the default role labels. Fix: run `/work-items:setup apply`, which copies the binding into `docs/conventions/work-items.yaml`.

### Changed

- The babysit-loop skill, the babysit safety reference and the pull-request create reference no longer describe a JSON binding.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
bump: major
---

### Removed

- The tracker seam no longer reads a repo-root `.work-item-tracker.json`. The binding is only the `tracker` mapping of `<home>/work-items.yaml` (or a file `WORK_ITEM_TRACKER_BINDING` names). A repository bound only by the JSON file now gets exit `3` from every seam verb. **Fix: run `/work-items:setup apply`**, which copies the JSON binding and its `.work-item-tracker.local.json` personal override under `tracker:` in `<home>/work-items.yaml` and `<home>/work-items.local.yaml`, and leaves the JSON files in place.
- The one-line `notice:` the seam printed when it read the JSON file is gone.

### Changed

- With no binding, the seam's exit `3` message (`wit_no_binding_reason` in `lib/binding.sh`) says why and names `/work-items:setup apply`: a repo-root `.work-item-tracker.json` that no longer binds, a `work-items.yaml` with no `tracker` mapping, a root where no convention home applies, or a missing `WORK_ITEM_TRACKER_BINDING` file. A broken convention-home pointer names `/work-items:setup check` instead, and missing shared resolver copies name a plugin reinstall. The jira, gitea and linear seeds and the onboard-adapter template print the same message.
- `/work-items:setup check` reports a binding that exists only in `.work-item-tracker.json` as FAIL, remediation `/work-items:setup apply`, instead of INFO.
- The seam contract, setup skill, README, schema and the skill bodies that resolve role labels no longer describe a JSON fallback.
2 changes: 1 addition & 1 deletion docs/contracts/config-cascade/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ its conformance cell.
| `code-tidying` | no-floor | `.claude/tidy-lanes/<lane>.md` | team only | team only; residual wholesale if no `## Merge semantics` | per-section when declared | declared deviation; no user-global or `*.local.*` personal override (#723). Team layer over a bundled default. A project lane declaring `## Merge semantics` merges per-section with its bundled lane (`Scope` per-section override, watch-for patterns additive, per `docs-prose` #701 and `shell-tooling` #724). Residual deviation: a project lane that declares nothing still resolves project-only wholesale, the first-match fallback retained in #701 so unmigrated consumer lanes keep working, undeclared at the layer that takes it. Personal variation is limited to lane names the team does not track, an uncommitted `.claude/tidy-lanes/<lane>.md` never added to the index; gitignoring a path the team already tracks does not make it personal |
| `code-metrics` | no-floor | `docs/conventions/code-metrics.yaml` (ADR 0064; schema `plugins/code-metrics/schemas/code-metrics.schema.json`) | all three | later layer | per-key | conforms (per-key override, declared because every value is a scalar or a closed list: `scope.exclude` and `lanes.<lane>.collectors.<measure>` replace whole), except declared divergences from "Resolution algorithm": (1) the root is `git rev-parse --show-toplevel`, else the working directory, and `CLAUDE_PROJECT_DIR` is not read (`plugins/code-metrics/scripts/resolve-config.py:221-234`; step 1); (2) no home-root or same-file classification of the team and personal override paths (`resolve-config.py:236-252`; step 2). The team layer is the docs file alone: the retired `.claude` team file of earlier releases is never read (`resolve-config.py:244-252`), and `/code-metrics:setup check` reports it. A layer outside the YAML subset reads as absent, and a value of the wrong shape is dropped by file, key and value and resolves from a valid higher layer, else the bundled default, never a lower layer; neither stops the run (`resolve-config.py:133-165,273-297`; ADR 0064 Decision 7). Unknown keys inert. Keys owned by [`plugins/code-metrics/reference/config.md`](../../../plugins/code-metrics/reference/config.md). Written (team layer only, carrying every declared key of a retired `.claude` file) by `/code-metrics:setup apply`; read by every audit skill. The consumer's `.claude/ecosystems/<lane>.yaml` files are a separate convention (ecosystem-commands); this surface does not absorb them. **Claim:** the plugin implements this row with the declared divergences above. **Basis:** `plugins/code-metrics/reference/config.md` "Layers and merge form" and the cited `resolve-config.py` lines. **As of:** 2026-11-02. **Recheck:** when that section adds a layer, changes merge form, or starts owning an ecosystem-commands key |
| `repo-fleet-hygiene` | no-floor | `.claude/repo-fleet-hygiene.conf` | user-global + team | `--config` then team then user-global | whole-file, no per-key | declared deviation; whole-file precedence (explicit `--config` > team > user-global fallback), no per-key merge, no personal override layer (#1099) |
| `work-items` | no-floor | the `tracker` mapping of `<home>/work-items.yaml`; the legacy `.work-item-tracker.json` (repo root) while a repository is not migrated | team + personal override | personal override on the allowlist | per-key personal override | declared deviation ([ADR 0015](../../adr/0015-bind-the-tracker-at-repo-root-with-an-allowlisted-personal-overlay.md)): layers live at the repo root, not under `.claude/`; personal override (`.work-item-tracker.local.json`) merges per-key over a deny-by-default allowlist (lease TTL, jira/linear/gitea auth identity, `docs`); deliberately no user-global layer, since a cross-repo personal rung would reopen the per-user provider trap the allowlist forecloses. Anchors at the repo root (`CLAUDE_PROJECT_DIR`, else git toplevel), no CWD climb. The personal override's gitignore line is outside the `.claude/**/*.local.*` one-liner, so `/work-items:setup apply` appends it, announced, a declared exception to the recommend default (ADR 0015) |
| `work-items` | no-floor | the `tracker` mapping of `<home>/work-items.yaml` | team + personal override | personal override on the allowlist | per-key personal override | declared deviation ([ADR 0015](../../adr/0015-bind-the-tracker-at-repo-root-with-an-allowlisted-personal-overlay.md), superseded by ADR 0075): layers live in the convention home, not under `.claude/`; personal override (`<home>/work-items.local.yaml`) merges per-key over a deny-by-default allowlist (lease TTL, jira/linear/gitea auth identity, `docs`); deliberately no user-global layer, since a cross-repo personal rung would reopen the per-user provider trap the allowlist forecloses. Anchors at the repo root (`CLAUDE_PROJECT_DIR`, else git toplevel), no CWD climb. The personal override's gitignore line is outside the `.claude/**/*.local.*` one-liner, so `/work-items:setup apply` appends it, announced, a declared exception to the recommend default (ADR 0015) |
| `work-items` (recurring schedule) | no-floor | `.github/recurring-schedule.json` | team only | team only | single-layer | declared deviation ([ADR 0042](../../adr/0042-ratify-consumer-config-location-outliers-in-place.md)): the schedule lives under `.github/`, not `.claude/`, tracked and team-shared with no user-global layer and no personal override. Written by `track add` and `track recheck`; read by `track audit`, `done`, `due`, `search` and `stats`, by `work` candidate discovery, and by `setup`, which also writes it; anchors at `CLAUDE_PROJECT_DIR`, else git toplevel. Separate from the tracker binding row above |
| `work-items` (settings keys) | any-layer-wins | team: `docs/conventions/work-items.yaml` (schema `plugins/work-items/schemas/work-items.schema.json`); per user: the plugin's `userConfig` option of the same name | `userConfig` + team | team; `true` in any layer for the five `bug_path.fix_gate` floors (policy floor) | per-key | conforms to the [location axis](#location-of-the-team-layer-a-docs-convention-file-or-claudename) ([ADR 0064](../../adr/0064-home-plugin-customization-in-docs-conventions-yaml.md)), with the layer order of its Decision 8: the manifest default, then `userConfig`, then the team file; no `~/.claude` file and no personal override. Keys are `triage_repro_count`, `triage_objection_window_hours` and `ai_disclaimer`; `triage_cluster` (signature-cluster defaults) has the team layer only. A value outside a key's range is named with its file, key and value, and that layer is dropped; the key then takes its manifest default, never a lower layer. This repository's file sets `ai_disclaimer: false`. The triage keys are read by `/work-items:triage` only, through `skills/triage/scripts/parse-concern-value.sh` from the repository root, or at a pinned ref under `--config-ref`; the `/work-items:work-loop` admission gate reads the window's end from the marker comment triage posts, not the file. `ai_disclaimer` is read through the same script by each lane that follows `plugins/work-items/reference/ai-disclaimer.md`. `bug_path.fix_gate` (team file only, no `userConfig` option) is read by `/work-items:work` through the same script with `--ref origin/<default-branch>`, so a branch cannot loosen it; its floor keys `confirmed_repro`, `evidence_reviewed`, `no_fix_artifact`, `no_human_claim` and `root_cause_evidenced` default `true`, and a `false` is named and ignored, while `before_after_runnable`, `budget_minutes` and `scope` are plain keys. Hand-edited, since `/work-items:setup apply` does not write this file yet |
| `guardrails` | no-floor | team: `docs/conventions/guardrails.yaml` (schema `plugins/guardrails/schemas/guardrails.schema.json`) | team only, over the plugin default | team | per-key | declared deviation: one key, `fix_request_post` (`block` default, `allow`), read by `hooks/block-fix-request-post.sh` from the session's repository (the payload's cwd) at its local `origin/HEAD`, never the working tree or index, and applied whichever repository the post targets; no personal override and no `userConfig` value of the key (the guard's `block_fix_request_post_enabled` switch stays a separate per-user escape). A value other than `allow` or `block`, or a file that does not parse, is named and keeps `block` |
Expand Down
10 changes: 5 additions & 5 deletions docs/contracts/loop-lane/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ App installed on that repository only: a machine user is a `User` and would pass

A lane escalates by creating or labeling a tracker item that carries the **`needs-human` role
label**, resolved through the consumer's tracker binding (`config.role_labels` of the `tracker`
mapping in `<home>/work-items.yaml`, else of the legacy `.work-item-tracker.json`) and
mapping in `<home>/work-items.yaml`) and
never compared as a string literal
([`label-taxonomy.md`](../../../plugins/work-items/reference/label-taxonomy.md#canonical-roles) owns
the canonical roles and the resolution). A machine-marked bot comment discriminates a
Expand Down Expand Up @@ -1147,8 +1147,7 @@ offer to persist the answer; the headless path never waits on one.

**Lane-editable config and the four sandbox conditions.** Every local lane reads some config at run
time that the lane's own process could edit (audited in #7680). work-loop and attend-queue read
the tracker binding (`docs/conventions/work-items.yaml`'s `tracker` mapping, else the legacy
`.work-item-tracker.json`) from the checkout, including the role labels that
the tracker binding (`docs/conventions/work-items.yaml`'s `tracker` mapping) from the checkout, including the role labels that
admission matches on. The triage step they run reads `docs/conventions/work-items.yaml` and
`docs/conventions/pr-pipeline.yaml` from the working tree when no `--config-ref` is given, and
both lanes read that `work-items.yaml` for `ai_disclaimer` the same way. The
Expand Down Expand Up @@ -1498,8 +1497,9 @@ binding resolves from the same root the tracker seam uses.

```bash
root="${CLAUDE_PROJECT_DIR:-$(git rev-parse --show-toplevel)}"
L=$({ yq -o=json -e '.tracker' "$root/docs/conventions/work-items.yaml" 2>/dev/null || cat "$root/.work-item-tracker.json"; } |
jq -r '.config.role_labels["human-gated"] // "needs-human"' 2>/dev/null || echo needs-human)
L=$(yq -o=json -e '.tracker' "$root/docs/conventions/work-items.yaml" 2>/dev/null |
jq -r '.config.role_labels["human-gated"] // empty' 2>/dev/null)
L=${L:-needs-human}
gh issue edit <n> -R "$R" --add-label "$L"
gh issue comment <n> -R "$R" --body "Parked by operator: <reason>."
```
Expand Down
2 changes: 1 addition & 1 deletion plugins/autonomy/reference/prerequisite-resolution.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ presence-gated with a documented fallback per the marketplace's seam-phrasing co
|---|---|---|
| Ecosystems | Toolchain seam (when the `toolchain` plugin is installed), reading *resolved* consumer state **with resolution-rung provenance**: consume only consumer-authored or repo-inferred rungs; an ecosystem present but `enabled: false` is not configured; uncommitted user-global and `.local.yaml` layers report unresolvable; **reject the seam's bundled-default rung** as repository evidence | Inference from the repo's own build files; never another plugin's bundled defaults |
| MCP enablement | Config-audit surface (when the sibling config-audit plugin is installed; marketplace id in README, since this `reference/` surface may not name vendors) | Report `.mcp.json` presence only; name enablement as unprobeable in provenance |
| Tracker | Work-item tracker seam: the `tracker` mapping of `docs/conventions/work-items.yaml`, else the legacy `.work-item-tracker.json`, plus the bound adapter's `capabilities.json` (when the `work-items` plugin is installed) | Treat tracker-dependent prerequisites as unestablished (`unknown`) |
| Tracker | Work-item tracker seam: the `tracker` mapping of `docs/conventions/work-items.yaml`, plus the bound adapter's `capabilities.json` (when the `work-items` plugin is installed) | Treat tracker-dependent prerequisites as unestablished (`unknown`) |
| Substrates, schedulers, observability | Autonomy setup skill's own discovery slices | Same plugin, no gate |
| Configured-surface enumeration | Each surface's own presence in the repo | Never by reading the config-cascade registry table (a conformance ledger, not a runtime inventory) |
| Ownerless signals (CI-config presence, flag-SDK presence) | Probes owned by this contract | N/A |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ need before the meeting discovers it.
Refinement-time discovery is the toil addressed: backlog sessions burn shared meeting time
finding out an item is not ready: acceptance criteria missing, fields absent, scope
unclear. The check does the recurring pre-refinement pass and annotates each item with what
is missing, so refinement starts from ready-or-annotated items instead of live archaeology.
is missing, so refinement starts from ready-or-annotated items and nobody re-investigates
missing details during the meeting.

## Trigger and cadence

Expand Down Expand Up @@ -75,7 +76,7 @@ Single-posture identity: `backlog-readiness-check` (bare class token).
| Connector entitlements | none. Access is `repo`, so the connector branch of [Access to prerequisites](../routines.md#access-to-prerequisites) does not apply |
| Connector entitlement rung | n/a (no connector). For `prod` / `product` / `org` / `ext`, entitlement binds at the [Org binding layer](../binding-seam.md#resolution-ladder) |
| `executor_class` merge cap | cited from [executor surface classes](../trigger-dispatch.md#executor-surface-classes). None: `executor_class` is deprecated and caps nothing. Merge policy for this identity is n/a (`C1`) |
| Repo needs | tracker binding via the work-item tracker seam (the `tracker` mapping of `docs/conventions/work-items.yaml`, else the legacy `.work-item-tracker.json`, + adapter `capabilities.json`); a deterministic repo-file probe that finds those files absent is `unsupported`; `unknown` only when the work-item seam cannot establish the fact (composition fallback) |
| Repo needs | tracker binding via the work-item tracker seam (the `tracker` mapping of `docs/conventions/work-items.yaml`, + adapter `capabilities.json`); a deterministic repo-file probe that finds those files absent is `unsupported`; `unknown` only when the work-item seam cannot establish the fact (composition fallback) |

## Admission and escalation

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ Single-posture identity: `duplicate-detection-sweep` (bare class token).
| Connector entitlements | none. Access is `repo`, so the connector branch of [Access to prerequisites](../routines.md#access-to-prerequisites) does not apply |
| Connector entitlement rung | n/a (no connector). For `prod` / `product` / `org` / `ext`, entitlement binds at the [Org binding layer](../binding-seam.md#resolution-ladder) |
| `executor_class` merge cap | cited from [executor surface classes](../trigger-dispatch.md#executor-surface-classes). None: `executor_class` is deprecated and caps nothing. Merge policy for this identity is n/a (`C1`) |
| Repo needs | tracker binding via the work-item tracker seam (the `tracker` mapping of `docs/conventions/work-items.yaml`, else the legacy `.work-item-tracker.json`, + adapter `capabilities.json`); a deterministic repo-file probe that finds those files absent is `unsupported`; `unknown` only when the work-item seam cannot establish the fact (composition fallback) |
| Repo needs | tracker binding via the work-item tracker seam (the `tracker` mapping of `docs/conventions/work-items.yaml`, + adapter `capabilities.json`); a deterministic repo-file probe that finds those files absent is `unsupported`; `unknown` only when the work-item seam cannot establish the fact (composition fallback) |

## Admission and escalation

Expand Down
2 changes: 1 addition & 1 deletion plugins/autonomy/reference/routines/issue-triage-sweep.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ Single-posture identity: `issue-triage-sweep` (bare class token).
| Connector entitlements | none. Access is `repo`, so the connector branch of [Access to prerequisites](../routines.md#access-to-prerequisites) does not apply |
| Connector entitlement rung | n/a (no connector). For `prod` / `product` / `org` / `ext`, entitlement binds at the [Org binding layer](../binding-seam.md#resolution-ladder) |
| `executor_class` merge cap | cited from [executor surface classes](../trigger-dispatch.md#executor-surface-classes). None: `executor_class` is deprecated and caps nothing. Merge policy for this identity is n/a (`C1`) |
| Repo needs | tracker binding via the work-item tracker seam (the `tracker` mapping of `docs/conventions/work-items.yaml`, else the legacy `.work-item-tracker.json`, + adapter `capabilities.json`); a deterministic repo-file probe that finds those files absent is `unsupported`; `unknown` only when the work-item seam cannot establish the fact (composition fallback) |
| Repo needs | tracker binding via the work-item tracker seam (the `tracker` mapping of `docs/conventions/work-items.yaml`, + adapter `capabilities.json`); a deterministic repo-file probe that finds those files absent is `unsupported`; `unknown` only when the work-item seam cannot establish the fact (composition fallback) |

## Admission and escalation

Expand Down
Loading
Loading