Skip to content

feat(instruction-placement): persist the delta baseline in the artifact-protocol baselines slot - #3831

Closed
kyle-sexton wants to merge 2 commits into
mainfrom
claude/3811-delta-artifact-slot
Closed

kyle-sexton wants to merge 2 commits into
mainfrom
claude/3811-delta-artifact-slot

Conversation

@kyle-sexton

@kyle-sexton kyle-sexton commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Closes #3811

Summary

The instruction-placement:delta lane kept its baseline behind lib/state-key.sh, whose key ends in a hash of the worktree's absolute root path. The sibling overengineering:delta persists the equivalent state through the shared lifecycle artifact protocol, so the marketplace carried two ways of keeping one kind of state, and the state-keyed one lost every operator decision at a checkout boundary.

This makes instruction-placement a protocol participant and moves both of its artifacts onto the protocol's memory tier. What the delta skill detects, its noise budget, and its report shape are unchanged, per the issue's out-of-scope list.

Fix

The implementation follows plugins/overengineering for the branch-keyed, concern-scoped memory home resolved through a plugin-local reference/topic-docs.md binding, with reference/artifact-protocol.md shipped as a byte-identical copy of docs/PLUGIN-ARTIFACT-PROTOCOL.md. It is not a byte-for-byte parallel: overengineering keeps a flat spine-baseline.md in its home root, while this plugin puts its baseline in the protocol's named baselines/ slot (the slot verification already uses), which is what the issue title asks for and what keeps the two names the protocol defines doing the job they were defined for. The home shape and the branch axis are shared; the leaf placement is this PR's own choice.

  • New plugins/instruction-placement/reference/artifact-protocol.md, registered in scripts/validate-plugin-contracts.mjs (lifecycleProtocolCopies) so drift fails CI.
  • New plugins/instruction-placement/reference/topic-docs.md: the placement binding, deltas only, owning the rung order, the branch slug, the runtime guards, and the retirement note.
  • Home moves to .work/instruction-placement/<branch-slug>/: findings.md, and baselines/delta-baseline.md.
  • delta now compares against that persisted baseline instead of against the findings artifact. The artifact is merged into by every audit and edited by every realign, so diffing it against itself measured whatever last touched the file. The baseline is captured at the end of a cycle, only by a cycle that consumed one, and carries the declined records forward as records of their own.
  • The first baseline is bootstrapped from the artifact (second pass, after review). audit and realign write no baseline and the end-of-cycle capture is earned only by consuming one, so as first shipped nothing ever wrote the first baseline and every delta run after an audit was a permanent route-out. delta step 1 now disposes of what it finds the way overengineering:delta step 2 does: baseline present and branch-matched is the baseline; findings.md present with no baseline (absent, or a branch: mismatch) is a bootstrap cycle that captures the artifact's spine rows and declined records over baselines/delta-baseline.md before it compares, then compares against that capture and says so in the report; only a missing artifact routes out. The one departure from the sibling is forced by composition: overengineering's delta invokes the audit itself, so its no-artifact case runs the audit and captures afterwards, while this delta does not compose audit and keeps routing to it. The contract (context/findings-artifact.md), the binding, and the changelog state the same disposition.
  • lib/state-key.sh is removed from this plugin, its three allowed-tools grants are gone, and scripts/sync-state-key.sh drops it from the cluster (four copies remain).
  • instruction-placement joins the topic-docs convention's reserved concern names; the convention goes to 3.2.0, additive, and gains an Implementers row. The reserved-name rule now distinguishes "flat" (no slice tree) from "no subdirectory ever", since baselines/ is the first concern-scoped use of the protocol slot.

Migration: nothing is migrated, and the absence is made detectable. Reading the old plugin-data tree would require keeping the worktree-hashed derivation alive as the parallel second home this change exists to close, which the issue explicitly forbids ("removed, not left in place as a fallback"). Instead the first delta or realign run after upgrading names the resolved home it looked in and routes to a full audit, rather than silently reporting a first run. The route-out message now also names the retired pre-0.12.0 tree as the likely cause, in one clause and without reading it, so a home the upgrade left behind and a plugin that never ran no longer look identical. After that audit, the next delta bootstraps its baseline from the artifact. The old tree is inert and can be deleted; the binding, the CHANGELOG, and the plugin README all say so.

One thing to look at, stated rather than glossed. The epic's cross-worktree criterion is delivered as far as the mechanism honestly goes and no further. The worktree-path hash is gone, so the home varies with the branch and the configured memory root rather than with where a checkout sits, and two checkouts resolving the same memory_dir on the same branch now share one home, which the state key made impossible by construction. Under the documented default the memory root is inside the checkout, so two checkouts still hold two homes; what changed is that a declined decision lives in one named file rather than behind an unreproducible hash. Full cross-checkout durability for an operator judgment needs a tracked suppression surface (docs/conventions/finding-suppression/, the shape overengineering uses), which this PR does not add and which is recorded as a revisit trigger in the plugin README instead of being implied.

Verification

New suite plugins/instruction-placement/scripts/artifact-home.test.sh (21 assertions) grades the documents, following the plugins/discovery/scripts/contract.test.sh precedent. Its load-bearing assertions catch this change's own failure mode: every baseline path named anywhere in the shipped surface must end in baselines/delta-baseline.md (the bare leaf delta-baseline.md is no longer tolerated, since a bare leaf at the read step means "beside findings.md", the second slot the binding warns about), and delta's read step and capture step are each located under ## Workflow and checked on their own, every baseline path inside the step carrying the slot. A write path and a read path that disagree raise no runtime error at all: the lane would bootstrap from the artifact on every cycle while depositing a capture nobody reads, indistinguishable from a healthy first delta after an audit.

Mutation-checked in both directions on the tightened suite, each mutation alone and restored byte-for-byte afterwards: rewriting only the read step's slot to delta-baseline.md fails every baseline path in the shipped surface resolves to baselines/delta-baseline.md and delta's read step names baselines/delta-baseline.md (2 assertions, exit 1); rewriting only the capture step's slot fails the sweep and delta's capture step names baselines/delta-baseline.md (2 assertions, exit 1). The earlier suite passed the read-step mutation, which is the vacuity the review found.

Command Result
scripts/affected-tests.sh --run exit 3 (success: 15 shell suites passed, 2 non-shell selected for their own lane)
all 9 plugins/instruction-placement/**/*.test.sh directly 9 PASS
plugins/instruction-placement/scripts/artifact-home.test.sh PASS, 21 assertions; both single-step mutation probes FAIL as intended
scripts/check-purged-em-dashes.sh 92 declared paths, 123 files, no em dashes
npx markdownlint-cli2 "plugins/instruction-placement/**/*.md" 19 files, 0 issues
scripts/check-changelog-parity.sh --check / --check-order / --check-bump origin/main / --check-preserved origin/main all 4 PASS
check-skill.sh plugins/instruction-placement/skills/delta PASS, 0 errors, 0 warnings
scripts/check-cross-plugin-source-drift.sh --check no unregistered or drifted clusters
scripts/sync-state-key.sh --check all 4 remaining copies match canonical
node scripts/validate-plugin-contracts.mjs 3335 plugin files checked, clean
shellcheck + shfmt -d on the suite clean

delta's description changed in the first pass (it now writes two files, not one), so the listing budget was re-measured then: aggregate 140855 → 140880 chars, +25, and the per-entry cap is 806/1536. The second pass leaves the description byte-unchanged, so no re-measure is owed. The fleet-wide WARN against the 8000-char documented default is pre-existing and unmoved by this PR.

Pre-existing and not from this change: plugins/claude-ops/skills/plugins/scripts/cache-content-check.test.sh (process-budget assertions) fails identically on a stashed, pristine tree, which is why scripts/check-changed-skills.sh origin/main reports one failing skill.

Neither docs/SKILL-CHEAT-SHEET.md nor docs/CATALOG.md needed a row: both are generated, and no summary or plugin description changed. No conflict with the concurrent #3810 lane.

Related

  • Parent epic: Epic: drift discoverability #3803 (drift discoverability). This is its third acceptance criterion, plus the fourth (the skill carries its own artifact-protocol reference).
  • Sibling implementation followed, with the baselines/ slot as this PR's own departure from its flat spine-baseline.md: plugins/overengineering/reference/topic-docs.md, plugins/overengineering/skills/delta/context/baseline-model.md, and the bootstrap disposition in plugins/overengineering/skills/delta/SKILL.md step 2.
  • Convention touched: docs/conventions/topic-docs/ 3.1.0 → 3.2.0, additive.
  • Deliberately untouched: the artifact protocol itself, the overengineering delta skill, and what this delta detects.
  • Running concurrently with codebase-health/audit: Boundary routes to the sibling drift lanes #3810 on a disjoint plugin tree.

🤖 Generated with Claude Code

https://claude.ai/code/session_01ViPsHkL3ng9xWt2GjEQJob

…ct-protocol baselines slot

The delta lane kept its baseline behind `lib/state-key.sh`, whose key ends in a
hash of the worktree's absolute root path. The sibling overengineering delta
persists the equivalent state through the shared lifecycle artifact protocol, so
the marketplace carried two ways of keeping one kind of state and the
state-keyed one lost every operator decision at a checkout boundary.

instruction-placement becomes a protocol participant. It ships
`reference/artifact-protocol.md`, registered in `validate-plugin-contracts.mjs`
so the copy stays byte-identical to the canonical doc, and a new
`reference/topic-docs.md` binding that owns placement. Both artifacts move to a
memory-tier, branch-keyed home: `findings.md`, and `baselines/delta-baseline.md`
in the protocol's named `baselines/` slot. `instruction-placement` joins the
convention's reserved concern names (topic-docs 3.2.0, additive).

delta now compares against that persisted baseline rather than against the
artifact, which every audit merges into and every realign edits, and the
baseline carries the declined records forward as records of their own.

A tree at the retired location is not migrated and not read: a read-side
fallback would keep the worktree-hashed derivation alive as the parallel second
home this change closes. The absence is made detectable instead, by naming the
resolved home that came up empty and routing to a full audit.

`scripts/artifact-home.test.sh` pins the read path and the write path to one
slot across every shipped surface. A capture step and a read step that name
different files raise no error at runtime, so that disagreement is caught here.

Closes #3811

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ViPsHkL3ng9xWt2GjEQJob
…slot per step

As shipped, nothing ever wrote the first baseline. `audit` and `realign`
write none, the end-of-cycle capture is earned only by a cycle that
consumed one, and a missing baseline routed out. Every delta run after
an audit was therefore a permanent route-out and no cycle could compare.

`delta` step 1 now disposes of what it finds the way the sibling
`overengineering:delta` does: baseline present and branch-matched is the
baseline; `findings.md` present with no baseline (absent, or a `branch:`
mismatch) is a bootstrap cycle that captures the artifact's spine rows
and declined records over `baselines/delta-baseline.md` before it
compares, then compares against that capture and says so; only a
missing artifact routes out. The one departure from the sibling is
forced by composition: overengineering's delta runs the audit itself, so
its no-artifact case runs the audit and captures afterwards, while this
delta does not compose `audit` and keeps routing to it. The route-out
message now names the retired pre-0.12.0 plugin-data tree as the likely
cause, in one clause and without reading it, so a home the upgrade left
behind and a plugin that never ran no longer read the same.

The contract, the binding, and the 0.12.0 changelog entry state the
bootstrap and the narrowed route-out, and the binding's three bare
`delta-baseline.md` mentions now carry the `baselines/` slot.

`scripts/artifact-home.test.sh` was vacuous in the read direction: the
sweep whitelisted the bare leaf, and the both-steps assertion counted
mentions across the whole file (>= 2 of 3), so the hard rule covered for
a mutated step. The bare-leaf allowance is gone, and the read step and
the capture step are each located under `## Workflow` and checked on
their own: every baseline path inside the step must end in the slot.
Mutating the read step alone to `delta-baseline.md` now fails two
assertions; mutating the capture step alone fails two; restored, the
suite passes with 21 assertions.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ViPsHkL3ng9xWt2GjEQJob
@kyle-sexton
kyle-sexton marked this pull request as ready for review September 6, 2026 08:55
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 6, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-06T09:00:39.685548Z 3b0f6e4 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Copy link
Copy Markdown
Contributor Author

Independent review and the fixes it forced — flipped to ready

Posted by the autonomous worker lane (vm-worker-202609050257). Commit 3b0f6e4d. This flip is the lane's handoff; the merge lane owns it from here. This lane does not merge.

The blocking finding: the feature was a dead end as first written

delta routed out when the baseline was missing, context/findings-artifact.md listed "no prior baseline" as a stopped-short case that writes none, and neither audit nor realign ever wrote one. Nothing in the plugin could bring a baseline into existence, so after any audit every delta run would route out forever and no cycle could ever compare.

Fixed by adding a bootstrap cycle in delta step 1, mirroring overengineering's dispositions: baseline present and branch-matched is the baseline; findings.md present with no baseline (absent, or a branch: mismatch) captures the spine rows and declined records over baselines/delta-baseline.md, compares against that capture, and reports the bootstrap; only a missing artifact routes out.

One forced departure, stated in the commit, the contract and the body rather than smoothed over: overengineering's delta composes its audit, so its no-artifact case runs the audit and captures afterwards. This delta does not compose audit, so it keeps routing to it.

The second finding: the guard test only looked like it guarded

scripts/artifact-home.test.sh passed when only the read step was mutated to the bare leaf delta-baseline.md — reading beside findings.md, the exact bug the binding warns about. Two causes: the sweep whitelisted the bare leaf, and the "both steps" assertion was >= 2 while three mentions existed, so the hard rule covered for a mutated step.

Now: bare-leaf allowance dropped, the whole-file count replaced by per-step checks that locate the read and capture steps under ## Workflow and require the slot inside each. Both probes confirmed:

Mutation Result
Read step alone → bare leaf FAIL, 2 assertions, exit 1
Capture step alone → bare leaf FAIL, 2 assertions, exit 1
Restored byte-for-byte cmp-verified, 21 assertions pass

Confirmed sound by the review, and left alone

Write and read paths agree on <home>/baselines/delta-baseline.md across all three delta mentions, the contract, the binding table, README and CHANGELOG. artifact-protocol.md is cmp-clean against docs/PLUGIN-ARTIFACT-PROTOCOL.md and all five sibling copies. No dangling state-key.sh callers. Fences respected (nothing from #3740, #3783, or #3745's files). Budget growth of +25 chars verified and justified as a one-clause accuracy fix.

Still partial, and said so

Issue criterion 2 (a declined record surviving a different worktree) stays unmet under the default per-checkout memory root. The worktree-path hash is gone and declined records ride in one named file, but full cross-checkout durability needs a tracked suppression surface. Closes #3811 is therefore a conscious triage call, not an implied pass — recorded in a dedicated paragraph, a README revisit row, and the binding's "Retired" section.

The absent-baseline message now also names the retired pre-0.12.0 plugin-data tree as a likely cause, without reading it, so an upgrade that lost a baseline is distinguishable from a plugin that never ran.

Gates: affected-tests.sh --run exit 3, all nine instruction-placement suites, four parity modes, validate-plugin-contracts.mjs (3335 files), cross-plugin drift, sync-state-key.sh --check 4/4, em-dash purge, markdownlint 19 files, check-skill.sh PASS 0/0, shellcheck and shfmt all clean.


Generated by Claude Code

@claude

claude Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 2m 33s —— View job


Security review complete

  • Gather context (PR body, diff via gh pr diff, changed files)
  • Invoke /review:security-review and follow its criteria
  • Post findings

No security issues found.

What this PR touches

This is a state-persistence refactor for the instruction-placement plugin: it moves the audit
findings artifact and adds a new delta-comparison baseline from a plugin-data path keyed by
lib/state-key.sh onto the shared, branch-keyed topic-docs memory tier (.work/instruction-placement/<branch-slug>/). The change is almost entirely prose (SKILL.md workflow steps, reference/topic-docs.md, context/findings-artifact.md) plus one script deletion, one new test script, and two small registration edits (scripts/validate-plugin-contracts.mjs, scripts/sync-state-key.sh).

Areas checked

  • Deleted lib/state-key.sh: this file previously sanitized an attacker-influenceable git remote URL before using it as directory path components (falling back to a hash for anything not matching a strict segment charset). Removing it is not a regression here: the new placement scheme keys on the branch name, not the remote URL, and git's own ref-format rules (no .., no path components beginning with .) already preclude the traversal shapes that script was defending against. No replacement guard was needed because the untrusted input the old guard existed for is no longer part of the path-construction inputs.
  • New scripts/artifact-home.test.sh: a read-only contract test over the plugin's own shipped files (find/grep/awk on fixed paths and constant patterns). No external or untrusted input.
  • allowed-tools changes in audit, delta, realign SKILL.md: only remove the now-unused Bash(${CLAUDE_PLUGIN_ROOT}/lib/state-key.sh:*) grant; no new tool grants added, so the surface shrinks.
  • scripts/validate-plugin-contracts.mjs / scripts/sync-state-key.sh: mechanical list edits (register the new reference/artifact-protocol.md copy, drop the retired cluster member). No logic change.
  • Branch-slug / path resolution prose (reference/topic-docs.md): documented the same way the existing overengineering plugin already does it, so this doesn't introduce a new pattern to evaluate independently.

No injection, path-traversal, authz, or secret-handling concerns identified in the diff.
· branch claude/3811-delta-artifact-slot

@claude

claude Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 4m 41s —— View job


Code review — /review:code-review

  • Gather context (PR body, changed files, diff)
  • Run /review:code-review procedure
  • Post inline findings
  • Post summary comment

Summary

Reviewed the diff against origin/main (via gh pr diff 3831) across all 17 changed files: the topic-docs convention bump, the new reference/artifact-protocol.md and reference/topic-docs.md bindings, the context/findings-artifact.md baseline contract, the three SKILL.md updates, the removal of lib/state-key.sh, and the new artifact-home.test.sh suite.

One finding, posted inline on plugins/instruction-placement/skills/delta/SKILL.md (lines 87-95):

Branch-mismatch bootstrap can silently destroy another branch's baseline. Step 1's "both present, branch: does not match" disposal says the stored baseline "is kept, not overwritten" and then routes to the bootstrap path — but that path captures over the exact same baselines/delta-baseline.md slot before comparing, and the plugin has no second slot for it to land in. That directly contradicts context/findings-artifact.md (lines 173-179), which says a mismatch's bootstrap write is "a separate write the mismatch does not earn a replacement of" — a guarantee the single-slot design (enforced by the new artifact-home.test.sh) can't actually honor. In the documented lossy-slug-collision case (two branch names slugging to one directory), branch B's delta run would overwrite branch A's baseline and its carried-forward declined records — the exact loss this PR's redesign is meant to prevent, and a violation of the skill's own hard rule that "a baseline the run did not consume is never overwritten." The new test suite only checks static path strings, so it doesn't catch this runtime behavior gap.

Everything else — the topic-docs convention bump, the reference/topic-docs.md binding's resolution rungs, the retirement of lib/state-key.sh and its sync-state-key.sh/validate-plugin-contracts.mjs registrations, and the delta bootstrap logic for the ordinary (non-colliding) case — reads consistent and correctly cross-referenced. I did not independently re-run the PR's listed verification commands (affected-tests.sh, markdownlint-cli2, shellcheck, etc.); those are author-claimed and unverified by me.

Branch: claude/3811-delta-artifact-slot

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Last security-reviewed head: 3b0f6e4db62cbe04d9e7ba96bf8986b243a668a5. On the next push, the relevance gate compares only the commits since this SHA; delete this comment to force a full re-review.

Comment on lines +87 to +95
- **Both present, `branch:` does not match.** No baseline, naming both branches. The stored file
is kept, not overwritten, and the run takes the bootstrap path below.
- **`findings.md` present, no baseline.** A **bootstrap cycle**. Capture the artifact's spine
rows and its declined records, per the contract's capture rules, over
`baselines/delta-baseline.md` in the same home **before comparing anything**, then continue
with that capture as this cycle's baseline. Say in the report that this is a bootstrap and
that a status change made before it is unobservable this cycle. This is the only path by
which a first baseline comes to exist: `audit` and `realign` write none, so the delta run
after any audit takes it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Branch-mismatch bootstrap silently destroys the other branch's baseline, contradicting both this step and the contract it's owned by.

Step 1 disposes of a branch: mismatch by saying the stored file "is kept, not overwritten, and the run takes the bootstrap path below" (lines 87-88). But the bootstrap path it points to (lines 89-95) captures "over baselines/delta-baseline.md in the same home before comparing anything" — the identical path. Since this plugin enforces exactly one stable baseline path per home (no per-branch filename, and artifact-home.test.sh pins that there is only ever one canonical path across the whole surface), there is nowhere else for that capture to land. The bootstrap write therefore overwrites the very file this bullet just said would be kept.

This also contradicts the contract this skill defers to, context/findings-artifact.md lines 173-179: "a branch: mismatch keeps the mismatched file too, since the bootstrap that follows is a separate write the mismatch does not earn a replacement of" — but no separate location is ever defined anywhere in the binding or the contract; the single-slot design (by construction) makes "separate write" unimplementable.

Concretely: two branch names that slug to the same directory (an explicitly acknowledged, documented case — "The slug mapping is lossy and two branch names can slug to one directory") will have branch A's delta run capture a baseline, then branch B's next delta run silently clobber it via the bootstrap-before-compare write, destroying branch A's declined records — the exact loss this whole baseline redesign exists to prevent ("A decline is the one judgment in this plugin that no other surface can reconstruct"). This also violates the skill's own hard rule at line 156: "A baseline the run did not consume is never overwritten."

artifact-home.test.sh only checks static path strings across the shipped docs, so it wouldn't catch this runtime behavior gap.

Fix this →

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3b0f6e4db6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +71 to +75
**Persisting at rungs 2 to 4 is ask-gated, never automatic.** Each of those rungs persists the
resolution to the concern file only on the user's explicit confirmation; declining is a valid answer
that leaves the resolution session-local, and the run proceeds either way. This is the one sanctioned
tracked write of the audit skill, whose read-only headline is scoped to unasked writes; every unasked
write it makes stays in the memory tier.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Align audit's hard rule with the new tracked write

At resolution rungs 2–4, this now instructs audit to persist .claude/topic-docs.yaml, but skills/audit/SKILL.md:166-167 still says its findings artifact is the only file it writes and forbids repository edits. The claimed scoping of the read-only headline was therefore not carried into the skill body, leaving first-run audits with mutually exclusive instructions: either skip the required persistence or violate their hard rule. Update the audit contract to disclose the explicitly confirmed concern-file write, or remove that write from this resolution flow.

AGENTS.md reference: AGENTS.md:L29-L29

Useful? React with 👍 / 👎.

Comment on lines +96 to +100
- **`findings.md` absent.** Route out. Name the resolved path you looked in, say that no
artifact is there, and route to the full audit rather than silently running one. On a
freshly upgraded plugin, name the retired pre-0.12.0 plugin-data tree as the likely cause,
in one clause and without reading it: a home the upgrade left behind and a plugin that never
ran look identical from here, and that sentence is what lets an operator tell them apart.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove upgrade archaeology from the delta skill

On every missing-artifact run, this tells the model to diagnose and narrate a specific pre-0.12.0 migration. That is version-specific historical guidance in an always-loaded skill body, contrary to the repository convention that skill bodies carry only the current rule and reason. Keep the current behavior—name the missing resolved home and route to an audit—but leave the retired path and version history in the reference document and changelog.

AGENTS.md reference: AGENTS.md:L29-L29

Useful? React with 👍 / 👎.

Comment on lines +87 to +91
- **Both present, `branch:` does not match.** No baseline, naming both branches. The stored file
is kept, not overwritten, and the run takes the bootstrap path below.
- **`findings.md` present, no baseline.** A **bootstrap cycle**. Capture the artifact's spine
rows and its declined records, per the contract's capture rules, over
`baselines/delta-baseline.md` in the same home **before comparing anything**, then continue

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid overwriting a mismatched branch baseline

When two branch names collide under the documented lossy slug mapping, this path first requires the mismatched baseline to be kept, then directs the bootstrap to write over that same canonical file. Overwriting destroys the other branch's unconsumed baseline; honoring the keep rule means the current branch never establishes a usable baseline and bootstraps again on every run. The mismatch case needs to route out or resolve a collision-disambiguated home rather than taking this overwrite-based bootstrap path.

Useful? React with 👍 / 👎.

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Claude has reviewed this PR 1 time. The lane skips further automatic reviews after 5; deleting this comment resets the count.

Copy link
Copy Markdown
Contributor Author

Merge lane claim — canonical for #3811, and why I am not advancing it to merge

Claimed at head 3b0f6e4db62cbe04d9e7ba96bf8986b243a668a5 by ccr-session-babysit-loop-20260906. No foreign activity in the preceding 30 minutes; untouched for roughly 9.5 hours.

Duplicate resolved

#3833 worked #3811 independently from a second worker-lane session, overlapping this PR on thirteen files including the identical lib/state-key.sh deletion. It is closed as superseded, on its red CI and its own verifier's "do not merge as-is" rather than on the number alone. The evidence is recorded there.

blocked is not CI

CI on this head is green. The ci-status and lint failure/cancelled entries are superseded runs; the latest of each is lint success at 08:55:19Z and ci-status success at 08:59:13Z. blocked comes from four unresolved review conversations, none outdated.

Why I fixed #3828's threads and am leaving these

Three of the four are ordinary branch-owned text fixes. The fourth is not, and it is the reason this PR stops here.

Two independent reviewers, Claude and Codex, converged on the same contradiction in skills/delta/SKILL.md Workflow step 1. I confirmed it in the source rather than taking either report:

  • The branch-mismatch case says the stored file "is kept, not overwritten, and the run takes the bootstrap path below" (lines 87-88).
  • The bootstrap path it routes into captures "over baselines/delta-baseline.md in the same home before comparing anything" (lines 89-95).
  • There is exactly one baseline path per home, so that is the same file. The mismatch case overwrites the file it just promised to keep.
  • The skill's own Gotchas hard rule says "A baseline the run did not consume is never overwritten."

context/findings-artifact.md calls the bootstrap "a separate write", but no separate location is defined anywhere in the binding or the contract, so under the single-slot design that phrase is unimplementable as written. The consequence is concrete: two branch names that slug to one directory, a case this PR documents as possible ("The slug mapping is lossy"), let branch B's next delta run silently destroy branch A's declined records. This PR itself calls a decline "the one judgment in this plugin that no other surface can reconstruct".

The reviewers named two mutually exclusive fixes: route out on mismatch instead of bootstrapping, or drop the "kept, not overwritten / separate write" language and admit the overwrite. Both change behavior, and picking one is a spec decision, not a cleanup. It also interacts with the larger open question below, so choosing here in isolation risks having to be undone.

The larger question, inherited from the closed duplicate

#3833's fresh-context verifier concluded that acceptance criterion 2 on #3811 does not hold, and that routing declines into the baselines slot mints a third suppression mechanism alongside docs/conventions/finding-suppression/. That finding applies to this PR too: it also carries declined records in the baselines slot, and its own body concedes that "Full cross-checkout durability for an operator judgment needs a tracked suppression surface ... which this PR does not add."

The verifier was explicit that the fix "amends the acceptance criteria on #3811, so it is a spec decision rather than a follow-up commit." I have recorded both questions on #3811 rather than deciding them from the merge lane.

This PR is held at blocked pending that decision. It is not stalled for lack of attention, and the work in it is sound apart from the one contradiction; it is waiting on a call that belongs to the issue.


Merge lane ccr-session-babysit-loop-20260906.


Generated by Claude Code

@kyle-sexton

Copy link
Copy Markdown
Contributor Author

Superseded by #3889, with evidence rather than a coin flip between duplicate lanes.

This PR is currently conflicting against main, and a diff check shows it carries neither of two fixes that came out of review on the other lane:

#3889 also carries three further review fixes from the same rounds: realign now writes the decline to the suppression surface, where it originates, because mirroring from the branch-scoped artifact meant the criterion's own sequence never propagated one; every resolution rung carries the branch segment, since the branch axis previously lived only in prose while rungs 1 and 5 stopped at the slice root; and a discovered finding is merged into the branch artifact before the spine advances, under a hard rule that the baseline never advances past an unrecorded discovery.

It is rebased onto current main, with the config-cascade implementers conflict resolved by keeping both the authoring-formats row that merged in #3874 and the instruction-placement row this work adds.

Closing this one is the cheaper reconciliation. If any of the above is wrong, say so on #3889 and I will fold this branch's version back in instead.

@cursor

cursor Bot commented Sep 7, 2026

Copy link
Copy Markdown

Closing as superseded by #3889. This branch is conflicting against main, and #3889 already carries the review fixes this lane does not. Do not merge.

@kyle-sexton kyle-sexton closed this Sep 7, 2026
kyle-sexton added a commit that referenced this pull request Sep 7, 2026
…d set across the right tiers (#3889)

## What

Moves the instruction-placement delta skill's persistence off the
ephemeral state key: the diff spine goes to the artifact-protocol
`baselines/` slot, branch-keyed, and declined findings go to a tracked
finding-suppression surface that git carries between checkouts.

Closes #3811.

> Supersedes #3833, which the babysit loop closed as a duplicate of
#3831. That was reasonable at the time, but #3831 is conflicting against
main and carries neither of the two review fixes this branch has,
described below. A closed PR does not track later pushes, so the work
sat stranded on the branch. This PR is that branch, rebased onto current
main.

## Why the first attempt was wrong

The original issue asked for the baseline to move to the
artifact-protocol slot "the same way the overengineering delta skill
uses", expecting a declined finding to survive into another worktree
from there. The sibling plugin does not work that way, and the
destination cannot satisfy the requirement.

The topic-docs convention states that a memory document is visible "only
in the checkout that wrote it", marks a sibling worktree `invisible`,
and refuses to carry that file class with `.worktreeinclude` ("never
baselines or raw scratch"). Git is the only mechanism that crosses
checkouts. So the two concerns split: the diff spine stays in the memory
tier where a per-branch artifact belongs, and the operator's judgment
rides a tracked file under the marketplace's finding-suppression
contract, which is exactly what the sibling plugin does.

## What review caught, across three rounds

- **The declined set never reached the baseline at all.** `realign`
wrote `declined` only into the branch-scoped findings artifact, and
`delta` mirrored from that same artifact, so the criterion's own
sequence never propagated a decline. Fixed by making `realign` write to
the suppression surface, where the decline originates.
- **The spine was not actually branch-local.** The branch axis lived in
prose while resolution rungs 1 and 5 stopped at the slice root, so two
branches sharing a resolved memory home would compare snapshots
describing different trees. Every rung now carries the branch segment,
and no branch identity resolves no home rather than falling back.
- **A discovered finding was reported once and then silently absorbed.**
A `new` or re-derived `changed` finding advanced the spine without being
persisted anywhere `realign` could act on it, so the next run no longer
saw it as movement. A merge step now runs before the spine capture,
under a hard rule that the baseline never advances past an unrecorded
discovery.
- **Glob-validation state was not carried.** With a rule file and its
glob text both unchanged, a previously-broken glob's state was lost, so
a re-run could not tell a still-broken glob from a newly-broken one. A
`RULE` row now carries the glob's validation verdict as of the capture,
and `broken-glob` is a transition rather than a state.
- **The bootstrap case was unhandled.** Step 1 enumerated only two
baseline/artifact combinations and omitted the ordinary one after a
first `audit` then `realign`, which resurrected a declined finding. All
four combinations are now tabled, and only the both-absent row routes
out.
- Plus a schema increment the document's own stability rule required, a
recorded anchor-collision trade, and an em-dash purge on surfaces that
declare it.

## Verification

`Plugin contracts validated: 3332 plugin files checked` · `CHECK-SKILL
delta|realign|audit|check|setup: PASS — 0 errors, 0 warning(s)` ·
`check-evals-quality: PASS` · `Linting: 22 files / Summary: 0 issues in
0 files` · changelog parity and newest-first both exit 0 · `No
unregistered or drifted cross-plugin source clusters found.` · `All 4
plugin copies match plugins/claude-config/lib/state-key.sh.`

## Rebase notes

Rebased onto current main through conflicts in the plugin manifest, the
plugin changelog, and the config-cascade implementers table. The
implementers conflict was resolved by keeping both rows:
`authoring-formats`, which merged today in #3874, and
`instruction-placement`, which this branch adds. They are different
surfaces.

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

https://claude.ai/code/session_012jiwedVq2GxuzN7siXQbr4

---------

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

instruction-placement/delta: persist baseline in artifact-protocol baselines/ slot instead of ephemeral state-key

2 participants