Skip to content

feat(claude-config): keep unhobble experiment state in the repo (#4094) - #5081

Merged
cursor[bot] merged 9 commits into
mainfrom
cursor/4094-unhobble-durable-state-37e9
Sep 28, 2026
Merged

cursor[bot] merged 9 commits into
mainfrom
cursor/4094-unhobble-durable-state-37e9

Conversation

@kyle-sexton

Copy link
Copy Markdown
Contributor

Closes #4094.

Summary

Phase 1 writes manifest.json and stumbles.md under .claude/unhobble/<experiment-id>/ and the strip commit carries them. Plugin data holds only backups. Identity is origin_url, branch, and base_commit (no absolute host path).

Test plan

  • Implementation + changelog/version on the branch
  • Reviewer: confirm restore/reclaim path keeps the ledger
Open in Web Open in Cursor 

@github-actions

Copy link
Copy Markdown
Contributor

PR body contract — issue linkage

This PR body does not yet satisfy the issue-linkage contract:

  • Missing a "## Fix" section. State the concrete change and how it addresses the problem.
  • Missing a "## Verification" section. Record concrete evidence the change works (commands, gates, output).
  • Missing a "## Related" section. List related PRs, ADRs, or decision-log entries this PR does not close.

Edit the body and this comment updates itself on the next run.

cursor Bot pushed a commit that referenced this pull request Sep 28, 2026
The resolver's 0.51.16 matches #5159. This PR's unhobble entry is 0.51.21.

Co-authored-by: Kyle Sexton <kyle-sexton@users.noreply.github.com>
cursor Bot pushed a commit that referenced this pull request Sep 28, 2026
Resolver numbers collided with #5159, #5162, #5153, #5081, #4827, and #4767. Headings are now claude-config 0.51.24 and 0.51.23, claude-ops 0.63.21 and 0.63.20, playbooks 0.13.24, and source-control 0.62.11 and 0.62.10.

Co-authored-by: Kyle Sexton <kyle-sexton@users.noreply.github.com>
cursoragent and others added 6 commits September 28, 2026 12:01
The nine must-fix rows are one funded version bump, not a patch on the
current state home.

Co-authored-by: Kyle Sexton <kyle-sexton@users.noreply.github.com>
Phase 1 writes the manifest and ledger under .claude/unhobble/<experiment-id>/
and the strip commit carries them. Plugin data holds only backups. Identity is
origin URL, branch, and base commit, with no absolute host path.

Closes #4094

Co-authored-by: Kyle Sexton <kyle-sexton@users.noreply.github.com>
The skill now records the repo state directory, so the out-of-scope deferral
no longer matches the branch.

Co-authored-by: Kyle Sexton <kyle-sexton@users.noreply.github.com>
Closes #4094.

Phase 1 writes manifest.json and stumbles.md under .claude/unhobble/<experiment-id>/
and the strip commit carries them. Plugin data holds only backups. Identity is
origin_url, branch, and base_commit, with no absolute host path.

## Summary

The experiment ledger is committed in the repo so a reclaimed container does not drop it.

## Fix

State files live under .claude/unhobble/<experiment-id>/. Backups stay in the plugin data dir. The manifest records origin_url, branch, and base_commit.

## Verification

check-skill, evals quality, changelog parity, and the em-dash gate passed on this branch.

## Related

Plugin ablation is #4095 and is not in this change.

Co-authored-by: Kyle Sexton <kyle-sexton@users.noreply.github.com>
gitleaks scans every remote branch. Commit f8ae237 adds fake
AccountKey and ApiKey fixtures in test scripts, the same class the
ignore list already covers.

Co-authored-by: Kyle Sexton <kyle-sexton@users.noreply.github.com>
The resolver's 0.51.16 matches #5159. This PR's unhobble entry is 0.51.21.

Co-authored-by: Kyle Sexton <kyle-sexton@users.noreply.github.com>
@cursor
cursor Bot force-pushed the cursor/4094-unhobble-durable-state-37e9 branch from 02a081d to 9f5c636 Compare September 28, 2026 12:01
cursor Bot pushed a commit that referenced this pull request Sep 28, 2026
Resolver numbers collided with #5159, #5162, #5153, #5081, #4827, and #4767. Headings are now claude-config 0.51.24 and 0.51.23, claude-ops 0.63.21 and 0.63.20, playbooks 0.13.24, and source-control 0.62.11 and 0.62.10.

Co-authored-by: Kyle Sexton <kyle-sexton@users.noreply.github.com>
cursoragent and others added 3 commits September 28, 2026 12:25
# Conflicts:
#	plugins/claude-config/.claude-plugin/plugin.json
#	plugins/claude-config/CHANGELOG.md

Co-authored-by: Kyle Sexton <kyle-sexton@users.noreply.github.com>
markdownlint MD012 flags the trailing blank line as two consecutive blanks.

Co-authored-by: Kyle Sexton <kyle-sexton@users.noreply.github.com>
# Conflicts:
#	plugins/claude-config/.claude-plugin/plugin.json
#	plugins/claude-config/CHANGELOG.md

Co-authored-by: Kyle Sexton <kyle-sexton@users.noreply.github.com>
@cursor
cursor Bot marked this pull request as ready for review September 28, 2026 12:39
@cursor
cursor Bot merged commit 2c6ad0b into main Sep 28, 2026
32 checks passed
@cursor
cursor Bot deleted the cursor/4094-unhobble-durable-state-37e9 branch September 28, 2026 13:03
kyle-sexton added a commit that referenced this pull request Sep 29, 2026
…e and permission lint (#5311)

Refs: #3563
Refs: #3568
Refs: #4027
Refs: #4094
Refs: #4113
Refs: #4114
Refs: #4115
Refs: #4116
Refs: #4583
Refs: #4600
Refs: #4656

## Summary

Fixes the `plugins/claude-config` findings from the audit of the
unattended Cursor PR run. Every change is inside
`plugins/claude-config/`; `hooks/exec-bash.mjs` is untouched.

- `audit-instructions`: the findings relay now follows `criteria.md`
(I31 and I33 surfaces, I32 tier by arm), `finding-ids.sh` refuses
non-instruction files under `$HOME`, `SKILL.md` records the
subagent-window claim and the I33 dispatch rule, and
`execution-and-report.md` (a second home for facts other files own) is
deleted.
- `unhobble`: delivers the #4094 must-fix items (product-surface class,
session branch, convention oracle test, `readd` refusal) and
nice-to-have items (`status` fields, ledger grouping, `decide`), and
removes silence as a deletion warrant (#3563).
- `audit-permission-state`: independent review of the #5154
`defaultMode` lint, which reached main under a "Do not merge" body with
no review.
- `audit`: the live-hook ask row carries the unattended-lane note
(#4600). `conflict-criteria.md` loses its dead repo-root link (#3568).
- `README.md` and `CHANGELOG.md` are corrected; version 0.52.0.

## Fix

- I15 link (#3568): `conflict-criteria.md` used six `../` segments that
resolved outside the repository, and an installed plugin does not carry
`docs/`. It now names the path in code font.
- Relay (#4116, #4656): `emit-findings.sh` admits I31 in any
skill-directory file and I33 in any skill-loaded file except `SKILL.md`,
names the nearest ancestor `SKILL.md` as the I33 hub, and tiers I32
CRITICAL under `plugins/` and IMPORTANT elsewhere. The persist-admission
text in `criteria.md` and `persist-findings.md` names the scanner (I28,
I29) and lane (I30 to I33) intakes.
- `finding-ids.sh` `surface_of()` (#4116, the security-lane finding left
open at merge of #4851): the user surface stays home-wide, and now
admits only instruction-file shapes. Basis: Claude Code reads
`CLAUDE.md`, `CLAUDE.local.md` and `AGENTS.md` from the working
directory and every directory above it, and follows imports to absolute
paths, so narrowing to `${CLAUDE_CONFIG_DIR:-$HOME/.claude}` would drop
real user surfaces. Any markdown file, `settings.json`,
`settings.local.json` and `hooks.json` inside a `.claude` tree or the
resolved `CLAUDE_CONFIG_DIR`, and files beneath a `skills/` directory in
those trees are admitted; `~/.ssh/config`, credentials, transcripts and
dotfiles are refused as `surface-not-an-instruction-file`. The scope
carries its four-part verification record in the code. This is the
citation for dismissing the open PR-comment finding on #4851.
`relativize_in_repo` is unchanged.
- `audit-instructions` docs (#4113, #4114, #4115, #4656): lane sizing
loses its ticket back-references, the subagent-window claim gets a
four-part record, the read-only contract covers lane reports and
run-state writes, I33 rows count as one dispatch outside per-lane
verifier batches, and `SKILL.md` regains line headroom under the
500-line cap.
- `audit-engine.sh` (#4600): the `HOOKS_LIVE=1` row ends with
`$lane_note`, like the other ask-rule rows.
- `unhobble` (#4094, #3563): the one-row watch disqualifier versus the
two-row re-add grammar is this skill's own rule (`SKILL.md` Phase 4 step
1), not an upstream one. `SKILL.md` and `evals/evals.json` (evals 27 to
30 added; 18 and 22 tightened). Items 1 to 4 and 7 of #4094 were already
on main (#5081). Items 5, 6, 8, 9 and 10 to 12 land here.
- #5154 review (#4027): `permission-state.sh` classified a settings file
`invalid-json` when the last key under `permissions` was a string,
because `jq -e` reads only the last output of a per-key check, so
`C2-defaultMode` and `C5-disableType` could not fire on real files.
Fixed with tests that fail against the old reader. The masking claim now
carries its condition, and the unsourced auto version boundary is
removed. Claims were checked against pages fetched 2026-09-29 (recorded
in the commit body).
- #4656 equivalence proof: regenerated at the #4839 pair; every output
matched byte for byte and the grep count is constant. Evidence only, no
change committed.
- `CHANGELOG.md` (#4027): the repeated 0.51.17 and 0.51.18 bodies became
pointers, 0.51.7 records that it shipped through #5154, and the header
notes the unreleased reserved versions.
- Cross-group requests applied (#4027): `criteria.md` I21 and the
`audit` effort-pin row state the effort defaults from the model-config
resolution order fetched 2026-09-28 (Opus 5.5 and Sonnet 5.5 default to
`medium`, Opus 4.7 to `xhigh`; the first-run-hold clause is gone), with
Verified, Source and the recheck trigger restamped. `unhobble`
`SKILL.md` and eval 15 stop restating the `block-hook-bypass` exit code
and heredoc coverage and defer to the hook.

In-place changelog corrections:

- 0.51.18: body replaced by a pointer; it repeated the 0.51.16 Fixed
entry (released by #5159) and a reworded near-duplicate of the 0.51.10
Changed entry (released by #5161).
- 0.51.17: body replaced by a pointer; it repeated the 0.51.15 entry
(released by #5156).
- 0.51.7: states it shipped through #5154 (commit 9c2db71), not #5059
(closed unmerged).
- File header: notes that 0.51.8 to 0.51.9 and 0.51.11 to 0.51.14 were
reserved by parallel branches and never released.

No issue is closed by this PR. #4094 stays on `Refs` because its 14-item
checklist is not verified complete here, and the others are
decision-held or have leftovers in other groups.

## Verification

Run in `/home/kyle/worktrees/ccp-fix-claude-config` after merging
`origin/main` (aebb9bb):

- All 34 `plugins/claude-config/**/*.test.sh` suites: exit 0 (includes
`emit-findings.test.sh`, `finding-ids.test.sh`,
`finding-identity.test.sh`, `permission-plane-lint.test.sh`,
`permission-state.test.sh`, `audit-engine.test.sh`, `lane-runs.test.sh`,
`instruction-files.test.sh`).
- `bash scripts/check-detector-findings-crosswalk.sh --check`: OK, 38
rule rows.
- `bash scripts/check-changed-skills.sh origin/main`: 4 skills checked,
0 failed.
- `bash scripts/check-changelog-parity.sh --check --check-order`,
`--check-bump origin/main`, `--check-preserved origin/main` (190
headings compared): pass.
- `bash scripts/validate-plugins.sh`: all manifests and the catalog
validated.
- `shellcheck` on every changed `.sh` file (the SC2016 hit on the
`emit-findings.test.sh` rule fixture line is suppressed with a reason)
and `check-evals-quality.sh` on the changed evals pass; `check-skill.sh`
warnings that remain were present on main.

#5154 review outcome (#4027):

- Claims checked: the `defaultMode` masking claim, the `permissions` key
shapes the lint reads, and the auto-mode version boundary, each against
Claude Code docs pages fetched 2026-09-29.
- Evidence: the masking claim holds only under a stated condition, now
carried in the text; the auto version boundary had no source and is
removed; `permission-state.sh` reproduced the `invalid-json`
misclassification when the last `permissions` key was a string.
- Defect fixed: the per-key `jq -e` check counted only the last output,
so `C2-defaultMode` and `C5-disableType` could not fire on real files.
New tests in `permission-state.test.sh` fail against the old reader and
pass now.

## Related

Audit report: `.work/audit/REPORT.md` findings by issue number: #3563,
#3568 (row 3c), #4027 (3b), #4094 (3b), #4113 (3b), #4114, #4115, #4116,
#4583, #4600, #4656 (3c).

Cross-group requests (not done here):

- core-docs: `docs/plugin-philosophy.md` #4583 structure and citation
defects, the `docs/upstream/claude-code.md` ledger re-point from #5059
to #5154, #5159 and #5161, the row 257-089 status, the FORCE decline
reconciliation, and review of the #5154 philosophy changes.
- playbooks: review of the #5154 boris changes.
- scripts: `check-changelog-parity.sh` should reject a CHANGELOG entry
whose body is byte-identical to an earlier entry.
- source-control: a body containing "Do not merge" must block the
unattended merge lane.
- review: closing comment on #3566.
- ci: reopen #4094 and comment that this PR delivers items 5, 6, 8, 9,
10 to 12.
- conventions: `docs/conventions/detector-findings/README.md` crosswalk
rows for I31, I32 and I33 restate the surface set and the I32 tier as
`criteria.md` defines them.

Cross-group requests received and not applied here:

- playbooks (docs/upstream row 257-083 rewrite): forwarded to core-docs,
which owns `docs/upstream/claude-code.md` and already edits that row.
- ci (#4094): items 5, 6, 8, 9 and 10 to 12 already land in this PR.
- review (#3566): the review group posts that comment.
- tracker (#4656): label removed and results noted on the issue.
- context-guard (row 260-002 home), context-budget (Items column),
skill-quality and session-flow follow-ups: added to the #4027 packet as
open questions. decisions-docs (#3568): both questions added to the
#3568 packet. Nothing implemented.

Issue operations done: #4027 and #4115 reopened with decision packets,
packets on #3568 and #4027 extended, comments on #4113, #4116, #4656,
#4583 and #3563.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01EugXnFddtpHcY5gTuyEirB

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

claude-config/unhobble: durable state, gate-aware strip plan, sourced carve-out, decide composition

2 participants