feat(hook-telemetry): marketplace-wide telemetry contract + markdown-formatter producer - #5
Conversation
Publish the marketplace-wide hook-telemetry convention: a versioned public-API contract for plugin hooks (producers) to emit structured execution telemetry to a consumer-set sink (HOOK_TELEMETRY_SINK, fire-and-forget, opt-in; unset = no-op). Carries this hook's own duration_ms, outcome, and findings — the per-hook signal CC-native OTEL structurally cannot provide (it reports aggregate total_duration_ms and excludes third-party plugin content). docs/conventions/hook-telemetry/: - README.md: spec — mediator boundary, fire-and-forget, best-effort/lossy guarantee; 7-field common envelope; status enum ok|error|skipped|blocked; hook_event free string; per-hook data + data/<hook>.schema.json discovery keyed on hook; forward-compat (additive-only, ignore unknown keys AND tolerate unknown enum values); deprecation policy; SemVer versioning; schemas are contract-docs (not machine-enforced); adopt-by-copy. - envelope.schema.json: draft 2020-12; required = all 7 common fields; additionalProperties true; status enum (4); duration_ms integer >= 0. - data/markdown-format.schema.json: required [tool, file, findings]. - CHANGELOG.md: schema_version 1.0 initial. - examples/markdown-format.json: worked fixture, consistent with both schemas. Contract authoring only; no runtime code. markdown-formatter is the first implementer (emit lands Phase 2). Verified (Tier-0, all PASS): fixture shape (schema_version/status/hook_event/ duration_ms/data); envelope additionalProperties + 4-value status enum; README forward-compat/deprecation/not-machine-enforced text; all 3 JSON parse. Lint deferred — markdownlint-cli2 absent locally. Co-Authored-By: Claude <noreply@anthropic.com>
First implementer of the hook-telemetry convention. The markdown-format hook now emits one telemetry envelope per run to a consumer-set sink (HOOK_TELEMETRY_SINK), fire-and-forget. Additive and opt-in: sink unset = no-op, with stdout and exit code byte-identical to before. hook-utils.sh: add hook::emit_telemetry <hook_id> <hook_event> <status> <start_epoch> <data_json>. Opt-in guard (sink unset -> return 0) + fail-open (jq absent -> return 0). duration_ms from $EPOCHREALTIME (locale-safe: handles . and , separators, 10# guards octal). timestamp via TZ=UTC printf (true UTC). Envelope built with jq -n (stderr -> /dev/null, never touches fd1). Background dispatch with the sink's stdout AND stderr -> /dev/null so it cannot block CC's stdout read to the 15s hook timeout (the C1 fd1-inheritance blocker) nor leak into additionalContext. markdown-format.sh: capture start before formatting; parse tool_name for data.tool; compute repo-relative data.file (cygpath -lm on Windows Git Bash to reconcile drive-letter vs mount form, plain prefix-strip on Linux/macOS, raw-path fallback); call hook::emit_telemetry LAST on the three post-format paths (markdownlint absent -> skipped; clean -> ok, findings []; residual -> ok, findings = violation lines filtered to the " MD<n>/" pattern). Pre-format exits (ext gate, missing file, kill switch) do not emit. stdin read once (INPUT=$(cat)) and fed to both the file_path and tool_name parses. Tests (TDD): markdown-format.test.sh PASS=41/0 (adds sink-set envelope validity, sink-unset additive-safety, non-zero sink, slow-sink C1 timing, stdout-leak); hook-utils.test.sh PASS=23/0 (sourced-lib unit). Shellcheck clean. Verified Tier-0 end-to-end: schema-valid envelope lands in sink; no fd1 leak; sink-unset produces no envelope with identical stdout; hook returns ~1.4s under a 3s sink (non-blocking). Co-Authored-By: Claude <noreply@anthropic.com>
…er-side
Resolve a relative HOOK_TELEMETRY_SINK against the caller's repo root so the
sink path is clone-portable and worktree-safe when wired via a tracked
settings.json env value (CC injects env literally, no ${VAR} expansion).
- hook::emit_telemetry: optional 6th repo_root arg ($CLAUDE_PROJECT_DIR
fallback, fail-open skip if neither); absolute paths pass through.
- Exec changed from unquoted $SINK to quoted "$sink": the sink is now a single
executable path (wrap in a script to pass arguments).
- markdown-format.sh passes its file-derived REPO_ROOT at all 3 emit sites
(CC #9447: CLAUDE_PROJECT_DIR can be empty in plugin hooks).
- Contract README gains "Sink path resolution"; CHANGELOG notes it under 1.0.
No schema_version bump - envelope wire-format unchanged.
- Tests: stub-script sinks replace command-with-args sinks + 4 resolution
cases (hook-utils 27/0, markdown-format 41/0).
Co-Authored-By: Claude <noreply@anthropic.com>
…contract docs A closed JSON-Schema enum on `status` contradicted the contract's own "consumers MUST tolerate unknown enum values" rule: a validator code-generated from the published schema would reject a future status value (JSON Schema 2020-12 sec 6.1.2). Relax `status` to a documented open string (mirrors `hook_event`), matching OpenTelemetry's open-enum pattern (`error.type`). - envelope.schema.json: drop the closed `status` enum; keep type:string and list the documented values in the description. - README: correct the `additionalProperties: true` claim (it encodes only unknown-keys-tolerated, not never-remove/rename — the rest is review/policy); record a deferred-with-trigger note for per-data versioning (CloudEvents `dataschema` precedent); add a consumer/sink adoption section. - CHANGELOG: 1.0 `status` documented as an open string, not a closed enum. Pre-publish correction — no schema_version bump. Validated against CloudEvents, OpenTelemetry semantic conventions, and JSON Schema 2020-12 (primary sources). Co-Authored-By: Claude <noreply@anthropic.com>
Bring the pre-CI-era telemetry files into conformance with the lanes #4 added: - hook-utils.test.sh: git mode 100644 -> 100755 (it carries a shebang; the exec-bit lane requires shebang scripts be 100755, matching its sibling). - Reword "mis-parse"/"mis-resolve" to plain English in the README sink-path note and two hook-utils.sh comments; the typos lane flags the bare "mis" token. Comment-only; no behavior change. Verified: hook-utils 27/0, markdown-format 41/0, shellcheck clean, typos clean.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d4826cde27
ℹ️ 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".
| FILE=$(hook::read_file_path) || exit 0 | ||
| # Capture $EPOCHREALTIME immediately after kill-switch so duration_ms covers | ||
| # the formatting work (pre-format exits below do not emit telemetry). | ||
| start=$EPOCHREALTIME |
There was a problem hiding this comment.
Avoid requiring Bash 5 for every hook run
On hosts whose env bash is Bash <5 (notably stock macOS /bin/bash 3.2), EPOCHREALTIME is unset; with set -u, this assignment aborts before stdin is parsed, so every Markdown edit fails instead of the hook's documented always-exit-0 behavior, even when telemetry is not configured. Use a portable timestamp source or guard this with a fallback before enabling telemetry timing.
Useful? React with 👍 / 👎.
| # variable — never to fd1. | ||
| local envelope | ||
| envelope=$(jq -n \ | ||
| --arg schema_version "1.0" \ |
There was a problem hiding this comment.
Emit a valid SemVer schema version
The new contract documents schema_version as SemVer, but the producer emits 1.0, which is not a valid SemVer 2.0 version because it lacks the patch component. Any sink that uses a standard SemVer parser or range comparison for this public contract will reject or mis-handle the first producer envelopes; emit 1.0.0 or explicitly document a non-SemVer two-part versioning scheme.
Useful? React with 👍 / 👎.
Address two more Codex P2 findings plus the analogous coaching case: - codebase-detection case (#2): the eval repo has no real auth-flow module, so grounding would fail or reward inventing sources. Reframe to the routing + graceful-degradation invariant — resolve to codebase mode, discover from live files, and ask the user to point when no grounding exists rather than inventing repo sources. - primary-source case (#5) and coaching case (#4): a fresh topic invocation runs the mission interview before teaching, so expecting immediate content rewarded skipping the mission gate. Make both gate-aware — respect the new-workspace mission flow while asserting the grounding / one-question-coaching invariants.
…opy through standards SSOT Corrector #4 reason-dont-recite (incumbency discipline): inherited content is evidence of what is, never self-justifying authority; a choice supported only by precedent earns first-principles re-derivation, not compliance. A distinct axis from do-your-research (acquire external evidence you lack — this questions internal evidence you inherited). SSOT: the consuming project's incumbency / first-principles rule, degrading to a portable baseline. A standards disagreement it surfaces routes upstream via follow-our-standards (routing only — that skill now owns "never silent deviation, never silent conformance"; no doctrine duplicated). point-dont-copy SSOT correction: its re-anchor step now routes through the org standards' reference-don't-duplicate (in-repo facts: literal/semantic, describe/use/expose roles, stable anchors) and documentation-and-citations (external facts: cite + fetch at read time, no upstream-inventory recap, citation placement) conventions instead of restating that doctrine. The skill keeps only its own pins — threshold two (tighter than the convention's three-or-more smell signal), point-at-public-contracts, no-capability- enumeration — and the not-a-copy carve-outs. Metadata, README, CHANGELOG updated; root catalog regenerated via scripts/generate-catalog.mjs. Corrector #5 (terseness) body authored and held pending its locked name. Co-authored-by: Claude Fable 5 <noreply@anthropic.com> 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Corrector #5 tighten-your-output (name locked): terseness discipline — say markdown in fewer words with no semantic loss, write code in fewer lines when readability holds. Code side re-anchors the consuming org's simpler-code convention (named failure modes: speculative generality / wrong abstraction / YAGNI; constraints never traded for line count). Markdown-terseness has no standards convention yet (verified against the standards engineering conventions), so the skill flags that gap rather than inventing a rubric and routes batch prose work to a compress capability's semantic-diff safety net; batch code to simplify. Distinct from point-dont-copy: this removes wasted words from one copy, not a second copy of a fact. Completes the plugin at five correctors sharing one engine doc. Metadata, README, CHANGELOG updated; catalog regenerated. 4 warranted evals. All gates green (markdownlint, skill-quality 0/0 x5, evals schema, plugin validate --strict). Co-authored-by: Claude Fable 5 <noreply@anthropic.com> 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Eval #4 exercised only the briefed-delegable open outcome. The closing invariant names status:needs-info as the other open outcome that must clear status:needs-triage, and its re-entry path differs (attention-view needs-info bucket on reporter reply, not the raw-marker bucket). Add eval #5 to prove an agent clears the raw marker on the needs-info outcome without orphaning the item. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…463) Two real findings from the PR review, both in the "Open linked PRs" adapter mechanic: 1. Missing word boundary — the keyword alternation had no lookbehind, so `fix` matched inside ordinary words (a body reading `prefixes #463` spuriously matched `fixes #463` and silently dropped the issue from the frontier). Add `(?<!\w)` (Oniguruma variable-width lookbehind, valid in jq). Verified: crafted `prefixes`/`suffix`/`unfixes`/`postfix` bodies now return false; real closing keywords still return true. 2. Inaccurate "truncation-safe per item" claim — `--search "<N> in:body"` is a coarse prefilter matching every PR mentioning the digit, so a small `<N>` (e.g. #5) can exceed the page cap and truncate the real closing PR (GitHub sorts by relevance, not recency). Raise the limit to 1000 (exceeds any realistic repo's open-PR count) and reword the prose to describe the prefilter/superset accurately instead of overclaiming. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ructions, docpage-digest, corpus graduation) (#1699) ## Summary Operationalizes the dual-verified Opus 5 corpus (prompting guide + system card) through existing seams, model-scoped behind the fleet-wide promotion gate: - **playbooks model-adaptation seam + `opus-5.md` chapter** — `context/opus-adaptation.md` generalized to `context/model-adaptation/<model-version>.md` (`opus-4-8.md` rescoped, `opus-5.md` new); SKILL.md meta-rule 3 now routes by model VERSION, killing the "apply them verbatim" family-level defect. playbooks 0.6.0. - **audit-instructions Opus-5 I8 rows + `--target-model`** — I8 gains Opus-5-scoped rows (instructed self-check removal, report-everything-vs-conservative with two criteria-owned fences, don't-think directives); I8/I10 model-scoped; `--target-model <version>` with fail-loud alias normalization; scan script + TDD fixtures extended (46 checks). claude-config 0.14.0, criteria 1.3.0. - **knowledge `docpage-digest` skill (0.10.0)** — fourth ingestion sibling: generic fetch → inventory → model-matched digest fan-out → dual cross-vendor verification → interview handoff, with the Anthropic docs profile as a separable context file (Rule of Three holds engine extraction). - **corpus graduation via [knowledge-corpus#5](https://github.com/melodic-software/knowledge-corpus/pull/5)** — both Opus 5 slices (originals + corrected-derived digests + verification records) under new `sources/docs/`, fresh dated graduation pins, byte-fidelity `-text` rule. **Merge of that PR stays with the human.** - **ADR 0006** — records the model-scoped-by-default doctrine + promotion gate. Phase 6 acceptance run: `docpage-digest` executed end-to-end on the live effort doc (`.work/effort/`, untracked) — full 5-level effort ladder captured (the guide's ladder was truncated; verified live), dual verification with degraded-verifier fallback recorded, `opus-5.md` effort cross-check NO DRIFT, pipeline friction folded back as skill fixes (`511d7f0e`). ## Test plan - [x] `instruction-scan.test.sh` — 46/46 pass - [x] `scripts/check-changed-skills.sh origin/main` — 0 failed - [x] markdownlint clean over all changed `.md` (one MD018 root-caused and fixed) - [x] `docpage-digest` evals.json validates against the skill-quality schema - [x] Phase 3 acceptance audit run (local-path marketplace install; `--target-model opus-5`; fences held, `skipped-for-target` verified with `fable-5`) - [x] Phase 6 e2e pipeline run — all sanity checks pass (source/INDEX/digest parity, dual verdicts, interview handoff) - [x] Dual verification on every authored artifact; degraded-Codex fallback recorded where it fired ## Related - knowledge-corpus#5 (corpus graduation — human merge) - #1697 (effort judgment recalibration hand-off) - #1698 (statusline prime-drift indicator, deferred) No linked issue — this PR closes none. #1697 and #1698 are follow-ups it FILES (Phase 7 tracker items), not issues it resolves. <details><summary>Approved PLAN (durable copy, pre-prune)</summary> # PLAN — opus-5-prompting-interview ## Brief Interview completed 2026-07-26 (sessions 13ea1cdf + continuation). Every answer validated by three independent fresh-context validators (Claude Opus 5, Claude Fable 5, Codex GPT-5.6 Sol high); verdicts + merged triage in `validation/`. Written to `.work` because the shared checkout moved to an unrelated task branch mid-session; graduate this file to `docs/topics/opus-5-prompting-interview/PLAN.md` on the build task branch. ### TLDR Turn the dual-verified Opus 5 corpus (prompting guide + system card) into: refreshed per-model doctrine in the existing `playbooks` model-adaptation seam, an Opus-5 model-delta rule class in `claude-config:audit-instructions`, a reusable doc-ingestion skill in the `knowledge` plugin, and graduation of the corpus to `knowledge-corpus`. Everything model-scoped with a defined fleet-wide promotion gate and a Claude-Code-applicability filter with teeth. ### Goal Make Anthropic's Opus 5 guidance operational in daily Claude Code sessions without adding instruction noise: remove instructed self-check scaffolding where Opus 5 runs, keep architected independent review, deliver model-matched deltas through existing seams, and codify the ingestion pipeline so the queued docs (Fable 5, Sonnet 5, effort, guardrails, choosing-a-model, best practices, blogs) repeat cheaply. ### Deliverables (build order suggested, plan phase decides) 1. **playbooks model-adaptation refresh** — generalize `plugins/playbooks/skills/fable-5/context/` to `context/model-adaptation/<model>.md`; add `opus-5.md` carrying: verified behavioral deltas; the architected-vs-instructed verification doctrine WITH the recorded residual tension (the reconciliation is inference — source line 25 vs 65/78/83 never reconciled upstream); thinking controls (Alt+T, `alwaysThinkingEnabled`, `MAX_THINKING_TOKENS=0`; Fable-5-only carve-out) + thinking-off leakage guidance + 400-at-xhigh/max constraint; deliverable-length calibration sentence verbatim (tested-phrasing exception); effort guidance (start high/default, low/medium liberal); injection-robustness note (auto-mode-0% qualifier; trigger names the Haiku-unmeasured gap; bug-bounty re-read linked to same trigger). Fix or retire the stale `opus-adaptation.md` (Opus-4.8-calibrated; guide reverses it on effort floor, per-edit-batch verifier dispatch, delegation bias, scope literalism; I15-shaped conflict with SKILL.md meta-rule 3) in the same change. Hard facts (pricing, IDs, effort ladder) POINT at the `claude-api` skill — never copied. Pinned agent defs use conditional framing ("if you are not X…") because spawn-time overrides can desync body text from the running model. 2. **audit-instructions extension** — extend I8 (model-era re-audit) with Opus-5 rows, not a parallel class: instructed self-check/double-check/re-verification removal; report-everything-vs-conservative detection (BEHAVIORAL, with scope fence — known false positive in code-tidying tidyings.md:102); don't-think/don't-reason directive check. Add explicit target-model argument (skills are model-blind) defaulting to the pinned fleet model. Migrate I8 and I10 to model-scoped per the promotion gate. Price the runtime/confirmation-gate cost. Report-only stays. 3. **knowledge plugin: 4th sibling ingestion skill** (name via tournament at build) — self-contained like book-distill/course-digest/youtube-digest; pipeline mechanics (fetch → inventory → digest fan-out → dual cross-vendor verification → interview handoff) generic/multi-purpose by design; the Anthropic profile (raw-`.md` fetch channel, CC-applicability filter, model-matched digest agents, doc queue, artifact targets) is a SEPARABLE context file so a second profile can join and the engine can be extracted at the third (Rule of Three). Check `review:fanout` overlap before duplicating dual verification. PROCESS.md queue migrates into it. 4. **knowledge-corpus graduation** — both slices, ALL unaltered originals (source.md, source.pdf via existing LFS `.pdf` rule, source.txt) + digests + verification records; new `sources/<category>/` sibling (docs category); follow the repo's source-URL convention (provenance + retention terms). Fix the mechanisms-research stale cell (skills DO accept `model` frontmatter — selects executing model, does not branch) before it graduates. 5. **Effort-doc slice** — run the pipeline on `platform.claude.com/docs/en/build-with-claude/effort` BEFORE building effort artifacts (guide's ladder is truncated; verified live). 6. **Effort judgment recalibration** — no eval suite exists; reframed from "sweep". Execute with the choosing-a-model routing-vet slice (task #18). Distinguish pinnable vs session-only effort lanes. ### Constraints - Model-scoped by default; fleet-wide promotion ONLY via the gate: an authoritative model-agnostic upstream doc states it, OR multiple model guides converge. - CC-applicability filter with teeth: every harness-applicability tag is a claim verified against live code.claude.com docs at tag time (answer 17 was the filter's first application and it missed by inference). - Verification doctrine: remove instructed self-checks on Opus 5; keep architected independent review. Re-check surfaces classified by reviewer INDEPENDENCE, not invocation source. Advisor counts on the stronger-model axis only (sees full conversation — not context-independent). - Mandatory-verification carve-outs regardless of model deltas: security review, destructive operations, managed-upstream-file changes, PR merge gates. - Point-dont-copy everywhere; local copies only for tested-verbatim phrasing or frozen verification snapshots (MD5-pinned corpus). - Primer/delta payload minimal — curated deltas only; instruction compounding applies to the primer itself. - `.work/` stays untracked; nothing commits without explicit decision; verdict files are historical records (errata pattern — corrections in corrections-applied files, never rewrites). - Session verifier policy for this workstream: dual verifiers (Claude high + Codex GPT-5.6 Sol high) on everything produced. ### Acceptance criteria - `opus-adaptation.md` conflict resolved: no surviving instruction tells Opus 5 to apply 4.8-calibrated counter-steers verbatim. - `context/model-adaptation/opus-5.md` exists; every claim carries source + CC-applicability tag; hard facts are pointers. - audit-instructions run over this repo + user scope surfaces the instructed-self-check findings with the Opus-5 target-model argument; scope fence keeps the known false positive out. - Ingestion skill re-runs the pipeline end-to-end on the effort doc (deliverable 5 doubles as its acceptance test). - Both slices resolvable in knowledge-corpus with intact MD5s + source-URL records. ### Captured assumptions - Architected-vs-instructed reading is inference shared by 4 digests + all 3 validators + both corpus verifiers; recorded as such in the delta chapter so a future upstream clarification has a landing spot. If Anthropic reconciles differently, cluster-1 decisions move together. - "Agent preloaded with a skill" seam (user recollection) — verify at build; not load-bearing. ### Out of scope - Chat-verbosity instruction (ground held by existing rules + harness). - Narration artifact (harness ships near-identical guidance; verified in two live system prompts). - New hallucination/uncertainty instruction (saturated behaviors; citation-strengthening only). - Routing-lane changes from injection data (deferred with trigger). - Paste templates for non-CC surfaces (no API-side prompt authoring exists today). - Figure-value recovery from the card PDF (unless a decision leans on a missing number). ### Deferred questions - Empirical: what does Claude Code send at thinking-off + xhigh/max (400 or clamp)? → /planning:plan (build-time test; docs silent). - Thinking-off usage opportunities (user: "anything else we could make use of… don't lose sight") → /planning:plan; record as exploration item with the delta chapter as its home. - Ingestion-skill name → /planning:plan (naming tournament; candidates: ingest, doc-distill, absorb). - Statusline prime-drift indicator (Fable proposal) → /planning:plan (cheap, optional). - SessionStart pointer-only auto-prime → deferred-with-trigger (manual priming proves forgettable). - USER-RESERVED: any fleet effort-pin change resulting from recalibration (dotfiles `.chezmoidata/claude.json` seam; never machine-local). - USER-RESERVED: committing/graduating any `.work` content beyond the knowledge-corpus move. ## Plan All sanity-check commands run under Git Bash (verified available: GNU grep, md5sum coreutils 8.32, git-lfs 3.7.1). ### Standards grounding No `.claude/standards.yaml` / `docs/standards/` index exists — resolution ladder rung 4 (inference from repo-declared docs). `.claude/topic-docs.yaml` absent → topic-docs documented default `contract_tier: branch` applies (convention: `docs/conventions/topic-docs/README.md`; the `:210` YAML is its illustrative example, not a repo setting). Surfaces loaded: | Surface | Sections cited | Layer provenance | |---------|----------------|------------------| | `CLAUDE.md` | Fresh-docs mandate (:8-27); plugin design rules incl. semver versioning (:29-43); branching & PRs (:51-55) | team/repo | | `AGENTS.md` | Synced standards overwritten not edited (:9-16); stage explicit paths (:18-22); Conventional-Commits PR titles (:24-27) | team/repo | | `README.md` | Repo shape + documented validation commands (exact lint/test invocations resolved here at build time) | team/repo | | `docs/MIGRATION-PLAYBOOK.md` | Skill-split-on-discovery-intent (:28-35); naming precedence (:95-168); evals warrant policy (:298-359); version-bump delivery (:373-382); knowledge-corpus decision record (:1370-1402) | team/repo | | `docs/conventions/topic-docs/README.md` | Contract-tier default (branch) + prune-before-merge lifecycle | team/repo | | CI (`.github/workflows/ci.yml`) | `changelog-parity-gate` (:452), `contract-slice-prune-gate` (:482), `skill-quality-gate` (:806), `portability-lint`, `shell-portability-lint`, `skill-leaf-name-gate`, `orphaned-fixture-gate` | team/repo | | User CLAUDE.md | pointer-not-copy; producer≠critic; fresh-docs verification posture | user-global | ### Phase 1: Contract commit + memory-slice hygiene [DONE] The contract slice (this PLAN + `design/design-resolution.md`) is already authored on disk, untracked — this phase COMMITS it (do not re-create or overwrite) and fixes the one known stale research cell before anything downstream cites it. **Files affected:** | File | Action | What changes | |------|--------|-------------| | `docs/topics/opus-5-prompting-interview/PLAN.md` | COMMIT | Already authored (this file); stage + commit as-is | | `docs/topics/opus-5-prompting-interview/design/design-resolution.md` | COMMIT | Already authored | | `.work/opus-5-prompting-interview/PLAN.md` | MODIFY | ADD a graduation header note (authoritative copy now at `docs/topics/...`); body KEPT INTACT until close-out completes its PR-body paste — pointer-ization is a Phase 7 step, never before, so the workstream always holds one durable copy (graduation of THIS file is explicitly instructed by the Brief header — briefed exception to the USER-RESERVED `.work` clause) | | `.work/opus-5-prompting-interview/model-conditional-mechanisms-research.md` | MODIFY | Fix stale "Skills/commands" cell: skills DO accept `model` frontmatter (selects executing model, does not branch); verify against live `code.claude.com/docs/en/skills.md` at edit time and cite the URL in the row. Living research doc — edited in place; errata pattern reserved for verdict files (verdicts are append-only historical records) | Work items: 0. Sync: `git fetch` + rebase the task branch onto `origin/main` (verified 8 commits behind at plan time; main's playbooks is 0.5.2, not the checkout's 0.5.1), then re-verify every version number and line citation this plan hardcodes. Version from-values below are plan-time observations — the phase re-reads them at start; bumps are relative (next minor), not absolute. 1. Pre-flight: confirm no file this plan touches is a managed materialization — check the local `melodic-software/standards` checkout's `distribution/sync-manifest.yml` for this repo's managed paths (expected: none of `plugins/**` or `docs/topics/**` are managed; record the check). 2. Verify the skills `model`-frontmatter claim against live docs (fresh-docs mandate); fix the cell with URL citation. 3. Commit (`docs(topics): graduate opus-5-prompting-interview contract`), explicit paths only. **Sanity Check:** - `git ls-files docs/topics/opus-5-prompting-interview/` lists `PLAN.md` and `design/design-resolution.md`. - `grep -A3 "^## Stress-test summary" docs/topics/opus-5-prompting-interview/PLAN.md | grep -c "dual review"` returns ≥1 (summary filled, not a placeholder). - `grep -E "selects the executing model" .work/opus-5-prompting-interview/model-conditional-mechanisms-research.md | grep -c "https://code.claude.com"` returns ≥1 (corrected claim + live citation on the same row). - Work-item-1 check output recorded in the phase notes (managed-path result). ### Phase 2: playbooks model-adaptation refresh [DONE] Review: code-design Generalize the model-adaptation seam and land the Opus 5 delta chapter (Brief deliverable 1). **Files affected:** | File | Action | What changes | |------|--------|-------------| | `plugins/playbooks/skills/fable-5/context/opus-adaptation.md` | MOVE | `git mv` → `context/model-adaptation/opus-4-8.md`; title/preamble stay 4.8-scoped; deltas unchanged (still valid for their calibration target) | | `plugins/playbooks/skills/fable-5/context/model-adaptation/opus-5.md` | CREATE | The Opus 5 delta chapter (content contract below) | | `plugins/playbooks/skills/fable-5/SKILL.md` | MODIFY | Meta-rule 3 rewritten: route by model VERSION to `context/model-adaptation/<model>.md`; kill "if you are Opus, apply them verbatim" (the I15-shaped conflict); update chapter-routing row + "What this skill is NOT" pointer | | `plugins/playbooks/skills/fable-5/context/orchestration.md` | MODIFY | Line 3 "the opus-adaptation chapter's concern" → model-adaptation phrasing (rename sweep) | | `plugins/playbooks/.claude-plugin/plugin.json` | MODIFY | Next-minor bump (main is at 0.5.2 → 0.6.0; re-verify post-rebase) | | `plugins/playbooks/CHANGELOG.md` | MODIFY | New-version entry per house shape; existing entries' `opus-adaptation` mentions stay (history) | `opus-5.md` content contract (each claim: source citation + CC-applicability tag, tags verified against live code.claude.com docs at tag time): - Verified behavioral deltas (from the 9 guide digests + card digests). - Architected-vs-instructed verification doctrine WITH recorded residual tension (reconciliation is inference; source line 25 vs 65/78/83 never reconciled upstream) — landing spot for a future upstream clarification. - Thinking controls: Alt+T, `alwaysThinkingEnabled`, `MAX_THINKING_TOKENS=0`, Fable-5-only carve-out; thinking-off leakage guidance; 400-at-xhigh/max constraint. Cites the probe artifact (below). - Thinking-off usage opportunities recorded as a tagged exploration item (this chapter is the designated home). - Deliverable-length calibration sentence verbatim (tested-phrasing exception to point-dont-copy). - Effort guidance: ONLY guide-verbatim model-scoped claims (start high/default; low/medium liberal). The effort ladder itself is a POINTER to the `claude-api` skill — never restated. Any claim that would need the effort doc is deferred to the Phase 6 cross-check (dependency noted there) — this keeps deliverable 5's ordering constraint honest without serializing Phase 2 behind the new skill. - Injection-robustness note: auto-mode-0% qualifier; deferred-with-trigger routing note whose trigger names the Haiku-unmeasured gap; bug-bounty re-read linked to the same trigger. - Hard facts (pricing, model IDs, effort ladder) are pointers to the `claude-api` skill. - Payload discipline: curated deltas only — instruction compounding applies to this file itself. - Public-repo quotation note: this plugin repo is PUBLIC; the chapter's one verbatim upstream sentence (deliverable-length calibration) ships with source attribution — record the de-minimis quotation rationale in the chapter's Sources section (licensing analysis, Phase 2's own pre-flight; the Phase 5 licensing pre-flight covers only the private corpus repo). Work items: 1. Pre-flight: sweep live branches/worktrees for concurrent edits to `plugins/playbooks/skills/fable-5/` (`git worktree list` + `git branch --contains` scan; the `docs/ignition-rebind-note` worktree is known to hold the same SKILL.md region) — sequence or rebase deliberately before rewriting. 2. Fetch live docs for every harness claim (thinking controls, settings keys); cite URLs in the chapter's Sources section. 3. Empirical probe, thinking-off + xhigh/max: record a dated observation artifact at `.work/opus-5-prompting-interview/build-verification/thinking-off-probe-<date>.md` capturing CC version (`claude --version`), relevant settings snapshot, method (observation point for the request/error), result (400 vs clamp), and limitations. `opus-5.md` cites it as session-observed (docs silent). Probe is non-mutating. 4. Author `opus-5.md` from corpus digests (curated, minimal). 5. `git mv` + preamble edit for `opus-4-8.md`; rewrite SKILL.md meta-rule 3 + routing row; fix `orchestration.md:3`. 6. Rename sweep via `docs-hygiene:rename-references` over LIVING surfaces only — `docs/topics/fable-field-guide-audit/**` and CHANGELOG history stay untouched (historical records; errata pattern). 7. Version bump + CHANGELOG. 8. Dual verification (fresh Claude high + Codex GPT-5.6 Sol high, text-embedded while task #15 open) of the chapter against the corpus; records land in `.work/opus-5-prompting-interview/build-verification/`; corrections applied to the ARTIFACT before commit (verification records themselves append-only). **Sanity Check:** - `grep -rn "apply them verbatim" plugins/playbooks/` returns 0 hits. - `ls plugins/playbooks/skills/fable-5/context/model-adaptation/` shows `opus-4-8.md` and `opus-5.md`. - `grep -rn "opus-adaptation" plugins/playbooks/ --include="*.md" | grep -v CHANGELOG` returns 0 hits. - plugin.json shows `0.6.0`; CHANGELOG has `## [0.6.0]`. - Point-dont-copy: `grep -cE "\\$[0-9]|per MTok|MTok" .../opus-5.md` = 0 AND `grep -cE "claude-[a-z]+-[0-9]" .../opus-5.md` = 0 (no API model IDs) AND `grep -icE "low.*medium.*high.*xhigh|xhigh.*max" .../opus-5.md` = 0 (no ladder enumeration). - Probe artifact exists and is cited: `grep -c "thinking-off-probe" .../opus-5.md` ≥ 1. - Required content markers each present (one grep per item): residual-tension label, verbatim deliverable-length sentence, exploration-item tag, auto-mode qualifier, Haiku-unmeasured trigger. - markdownlint (repo's documented command) passes on changed files; `portability-lint` expectations hold (no machine paths). ### Phase 3: audit-instructions Opus-5 extension [DONE] Review: code-design Extend I8 with Opus-5 model-delta rows (not a parallel class), add target-model semantics, and model-scope I8/I10 per the promotion gate. **Target-model semantics (the deliverable's hinge):** the skill gains `--target-model <value>` taking a model VERSION (e.g. `opus-5`). Default resolution: read the resolved settings `model` value, then normalize alias→version against live model docs at run time; the pinned fleet value is an alias with a context-window suffix (verified this session: `opus[1m]`, settings.json:438), so normalization MUST fail loud when the alias is version-ambiguous and demand the explicit argument — never silently treat `opus` as `opus-5`. Model-scoped rows FIRE only when the resolved target matches their scope; otherwise they are inert (report lists them as skipped-for-target). The value is data — no hardcoded model branch in prose. **Files affected:** | File | Action | What changes | |------|--------|-------------| | `plugins/claude-config/skills/audit-instructions/reference/criteria.md` | MODIFY | I8 gains Opus-5-scoped rows: (a) instructed self-check/double-check/re-verification removal — carve-out lanes (security review, destructive ops, managed-file changes, PR merge gates) + independence classification (architected review survives); (b) report-everything-vs-conservative detection, BEHAVIORAL, with TWO fences: restraint-clause shape (the `tidyings.md:102` "When NOT to apply" case) AND quoted/meta-surface exclusion (documents that DISCUSS the pattern — criteria.md itself, the opus-5 delta chapter — are not findings); (c) don't-think/don't-reason directive check. Fences OWNED here (the model lane adjudicates; scanner stays advisory). I8 + I10 annotated model-scoped (single-model guide sources; promotion gate unmet). Criteria version 1.2.0 → 1.3.0 | | `plugins/claude-config/skills/audit-instructions/SKILL.md` | MODIFY | `argument-hint` + parsing for `--target-model`; normalization + fail-loud rule above; cost pricing: report header states added per-surface check count + estimated token delta AND confirms zero new interactive gates (report-only unchanged) | | `plugins/claude-config/skills/audit-instructions/scripts/instruction-scan.sh` | MODIFY | ADVISORY candidate patterns only (self-check phrasing, don't-think, conservative-phrasing) — over-production is by design per the script's own contract; header/`--help` updated to list the new pattern families | | `plugins/claude-config/skills/audit-instructions/scripts/instruction-scan.test.sh` | MODIFY | TDD: failing cases first. Positive fixtures: instructed self-check, don't-think, "be conservative" directive. Negative fixtures at the CRITERIA level are exercised via the acceptance run (fence is criteria-owned); scanner tests assert candidates are EMITTED for all shapes including tidyings-like text (advisory over-production is correct scanner behavior) | | `plugins/claude-config/.claude-plugin/plugin.json` | MODIFY | 0.13.0 → 0.14.0 | | `plugins/claude-config/CHANGELOG.md` | MODIFY | 0.14.0 `### Added` bullets per house shape | Work items: 1. TDD: scan-script fixtures (failing) → patterns (green); `shell-portability-lint` constraints respected (no GNU-only constructs). 2. Author I8 rows + both fences + model-scope annotations (I8, I10) in criteria.md. 3. Target-model argument + normalization + cost pricing in SKILL.md. 4. Version bump + CHANGELOG. 5. Acceptance run (AFTER Phase 2 lands — a clean playbooks result proves the conflict fix). PRECONDITION (verified this session): the audit resolves plugin surfaces from the SELECTED install record's cache path and rejects tree-walking (SKILL.md:115, :172-176) — the repo working tree is invisible to it. So FIRST install the task branch as a local-path marketplace (repo ships `.claude-plugin/marketplace.json`) so the selected install records point at the branch's playbooks/claude-config; record the install-record switch and its revert in the phase notes. Then run the audit over this repo + user scope with `--target-model opus-5` under Git Bash; report path resolved from `${CLAUDE_PLUGIN_DATA}/audit-instructions/last-audit.md` at run time. Fallback if local-path install proves unavailable: re-scope this run as post-merge verification and drop the Phase 2 → Phase 3 dependency edge (record the re-scope). 6. Dual verification of criteria/SKILL diffs; records in `build-verification/`. 7. Line budget: SKILL.md is 314/500 lines with a soft-target WARN already firing — additions (argument parsing, normalization rule, cost line) capped at ~60 lines; overflow goes to a `reference/` spoke. **Sanity Check:** - `bash plugins/claude-config/skills/audit-instructions/scripts/instruction-scan.test.sh` exits 0. - `grep -c "target-model" plugins/claude-config/skills/audit-instructions/SKILL.md` ≥ 2; criteria frontmatter shows `1.3.0`. - Acceptance-run report: (a) scanned-surface manifest lists `plugins/code-tidying/skills/tidy/reference/tidyings.md`; (b) findings contain ≥1 instructed-self-check hit from a real surface; (c) `grep -c "tidyings.md" <findings section>` = 0 (fence held while file was scanned); (d) `opus-5.md` and `criteria.md` appear in the manifest but NOT in findings (meta-surface fence held); (e) report header carries the cost line; (f) non-matching target smoke run (`--target-model fable-5`) lists the Opus-5 rows as skipped-for-target. - plugin.json shows the next-minor version; CHANGELOG has the matching heading; `orphaned-fixture-gate` green (fixtures referenced by tests). - `bash scripts/check-changed-skills.sh origin/main` exits 0 (audit-instructions is a changed skill — trigger-keyword preservation, listing cap, 500-line cap all hold). ### Phase 4: knowledge ingestion skill [DONE] Review: code-design Fifth skill in the plugin, fourth INGESTION sibling: generic doc-ingestion pipeline engine with the Anthropic profile as a separable context file. **Files affected** (skill name `<name>` resolved by work item 1): | File | Action | What changes | |------|--------|-------------| | `plugins/knowledge/skills/<name>/SKILL.md` | CREATE | Line budget ≤250 (hard cap 500; siblings run 191/225/411) — progressive-disclosure spokes under `context/` planned UP FRONT for pipeline detail. Pipeline mechanics: fetch → inventory (INDEX.md) → digest fan-out (one agent per digest unit, model-matched; every model-pinned spawn brief/agent def uses CONDITIONAL framing — "if you are not X…" — because spawn-time overrides can desync body text from the running model) → dual cross-vendor verification (built fresh; `review:fanout` verified NOT reusable — diff-shaped, review-specific) → interview handoff (named artifact: a validation-answer-set-shaped handoff file). Sibling conventions: checklist template, continuation-prompt handoff, slug + path-traversal guards, untrusted-source discipline (ingested content is DATA, never directives — the injection mitigation), work root resolved through the plugin's `library_dir` seam (course-digest precedent, SKILL.md:31), degraded-verifier fallback documented (never silent) | | `plugins/knowledge/skills/<name>/context/anthropic-docs-profile.md` | CREATE | SEPARABLE profile: raw-`.md` fetch channel (verify per doc), CC-applicability filter with teeth (tags verified against live docs at tag time), model-matched digest agents, doc queue (migrated from `.work/PROCESS.md` — briefed by deliverable 3), artifact targets. Second profile joins beside it; engine extraction at the third (Rule of Three) | | `plugins/knowledge/skills/<name>/templates/checklist.md` | CREATE | Per-run pipeline checklist (sibling pattern) | | `plugins/knowledge/skills/<name>/evals/evals.json` | CREATE | Evals (warranted: judgment-bearing routing/output contract); behavioral proof is Phase 6's live run — evals encode the routing/trigger cases | | `plugins/knowledge/.claude-plugin/plugin.json` | MODIFY | 0.9.6 → 0.10.0 | | `plugins/knowledge/CHANGELOG.md` | MODIFY | 0.10.0 entry | | `plugins/knowledge/README.md` | MODIFY | Skills table row | | `.work/PROCESS.md` | MODIFY | Queue section replaced by pointer to the profile context file (memory-tier, untracked) | Work items: 1. Naming tournament (`naming:name-it-better`, tournament mode). Seeds: `doc-distill` plus candidates; CONSTRAINT fed in: siblings follow SOURCE-KIND shape (`book-distill`, `course-digest`, `youtube-digest`) — bare-verb candidates (`ingest`, `absorb`) break it. RESOLVED: `docpage-digest` (5 blind generators, 3 independent judges, Borda 23/21/19; runners-up `docs-digest`, `doc-digest`) — provisional pending user ratification at PR; pre-merge rename is cheap via `docs-hygiene:rename-references`. 2. Author SKILL.md + profile + templates + evals. 3. `skill-quality:check`; fix findings. 4. Version bump + CHANGELOG + README. 5. Dual verification of the skill body against PROCESS.md semantics (no pipeline step dropped); records in `build-verification/`. Out of scope (explicit): sweeping the 8 pre-existing pinned agent defs (`plugins/discovery/agents/*`, `plugins/review/agents/*`) for conditional framing — they carry no model-delta doctrine text; the Brief clause governs artifacts THIS workstream authors. Recorded as a decisions-table row; revisit if a model-delta chapter ever lands inside an agent body. **Sanity Check:** - `scripts/check-changed-skills.sh` passes; evals.json validates against `plugins/skill-quality/reference/evals.schema.json`; `skill-leaf-name-gate` green. - `grep -c "prompting-claude-fable-5" .../context/anthropic-docs-profile.md` ≥ 1 AND queue-entry count in the profile ≥ the count in `.work/PROCESS.md`'s pre-migration queue (no entry dropped). - `grep -c "if you are not" .../SKILL.md` ≥ 1 (conditional-framing contract present). - `grep -ci "library_dir" .../SKILL.md` ≥ 1 (work-root seam, not a hardcoded path). - plugin.json `0.10.0`; CHANGELOG `## [0.10.0]`; README table lists `<name>`. ### Phase 5: knowledge-corpus graduation [DONE] Cross-repo phase (repo: `melodic-software/knowledge-corpus`, local checkout verified; own branch + PR there). **Hash doctrine (split two concepts — audit-time pins vs graduation pins):** the prompting slice's recorded pin (`opus-verdict.md:44-55`) predates 28 applied corrections; only `source.md` still matches. So: (a) immutable UPSTREAM ORIGINALS (`source.md`, `source.pdf`, `source.txt`) are verified against existing pins where one exists and pinned fresh where none does; (b) derived artifacts (INDEX, digests — corrected-derived, NOT unaltered — and verification records) get a FRESH dated graduation pin per slice; (c) `PROCESS.md` is dropped from any pinned set (moved + still-living file). Existing verdict files are never rewritten. Acceptance criterion "intact MD5s" is met as: originals bit-identical to `.work`, all files covered by a current pin record. **Files affected (knowledge-corpus repo):** | File | Action | What changes | |------|--------|-------------| | `sources/docs/opus-5-prompting/**` | CREATE | Full slice copy: source.md (original), INDEX.md + digests/ (9, corrected-derived) + verification/ (3) | | `sources/docs/opus-5-system-card/**` | CREATE | Full slice copy: source.pdf (LFS via existing `*.pdf` rule) + source.txt (originals); reflow_78_105.txt (tool-DERIVED, pinned under the derived-artifact rule); INDEX.md + digests/ (9) + verification/ (6 incl. tool.py) | | `sources/docs/opus-5-prompting/README.md` | CREATE | Provenance, required fields: canonical origin URL, fetch date, fetch channel (raw `.md`), retention terms | | `sources/docs/opus-5-system-card/README.md` | CREATE | Same fields + PDF origin | | `sources/docs/opus-5-prompting/verification/graduation-pin-2026-07-26.md` | CREATE | Fresh dated MD5 manifest: every file in the slice, with per-file original/corrected-derived label; notes the audit-time pin divergence cause (corrections-applied) | | `sources/docs/opus-5-system-card/verification/graduation-pin-2026-07-26.md` | CREATE | Same (this slice had NO prior pin — first hash record) | Work items: 1. Target-repo grounding FIRST: read knowledge-corpus README/AGENTS.md (if present)/`.gitattributes`; confirm provenance placement precedent (`sources/books/pat-pattison/README.md`) and LFS policy before finalizing the file list. 2. Licensing pre-flight: confirm retention authority (private org repo; Anthropic-published docs) and record terms in both READMEs; if terms forbid retention of any artifact, fall back to pointer-only for that artifact and record the substitution. 3. Generate PRE-COPY hash manifests from `.work` originals; copy; generate POST-COPY manifests; diff the two (this replaces any `git status`-based check — `.work` is self-ignored, git cannot see mutations there). 4. Verify `source.md` against the audit-time pin (`8579d63fc9f793784b8c56320fd74e71`); author both graduation-pin records. 5. Author both provenance READMEs; dual verification of the two READMEs + pin-record prose (mechanical hash blocks exempt — reasoned carve-out: hashes verify themselves); records in the plugins repo's `build-verification/`. 6. Branch + PR in knowledge-corpus (Conventional-Commits title); merge stays human. SHIPPED: knowledge-corpus PR #5 (commit 557bc4bd), merge human; byte-fidelity rule sources/docs/** -text added after CRLF normalization would have broken 6/19 pin rows on fresh clones. **Sanity Check:** - `git lfs ls-files` lists `sources/docs/opus-5-system-card/source.pdf`. - Pre-copy vs post-copy manifest diff is empty (exit 0). - `md5sum` of graduated `source.md` equals the audit-time pin value. - Both graduation-pin records enumerate every file in their slice (file count in pin = `find <slice> -type f | wc -l` minus the pin itself and README). - Both READMEs contain all four field labels (origin URL/statement, fetch date, channel, retention terms) — one grep per label. ### Phase 6: effort-doc pipeline run (ingestion-skill acceptance test) [DONE] Run the new skill end-to-end on `https://platform.claude.com/docs/en/build-with-claude/effort`. Deliverable 5 (effort slice BEFORE effort artifacts) + e2e acceptance test for Phase 4. Work items: 1. Invoke the skill with the effort-doc URL; it fans out its own digest/verify agents (this phase's sub-agent use is the skill's design, not an orchestration choice here). Outputs land at the skill's `library_dir`-resolved work root — record the resolved root in the phase notes; all checks below run against it. 2. Verify the full pipeline contract executed: source + INDEX + digests + dual verification + the interview-handoff artifact. 3. Cross-check `opus-5.md`'s effort section against the verified effort slice (the deferred dependency from Phase 2); amend `opus-5.md` in the same branch if drift found. 4. Record pipeline friction as Phase 4 fixes (same branch). 5. Commit ONLY if tracked files changed (skill fixes, opus-5.md amendments); the slice itself lives under the untracked work root — no empty commits. RAN: working-tree contract on .work/effort/ — all sanity checks pass, full 5-level ladder captured, opus-5.md cross-check NO DRIFT, friction fixes 511d7f0e; record: build-verification/phase6-effort-pipeline-run-2026-07-27.md. **Sanity Check:** - Resolved work root contains `source.md`, `INDEX.md`, ≥1 digest, 2 verification verdicts (each naming vendor + model + effort), and the interview-handoff artifact named by the skill contract. - INDEX digest inventory rows = digest file count (parity). - Effort ladder completeness: the slice's source.md contains every effort level the live doc states, including the one the guide truncated (assert per the live doc's own enumeration at run time, not a hardcoded token). - Phase-notes entry records the resolved work root + cross-check verdict (drift/no-drift). ### Phase 7: recalibration hand-off + close-out prep [TODO] Deliverable 6's EXECUTION is deferred by the Brief itself to the choosing-a-model routing-vet slice (session task #18) — this phase files the tracker items and records the lane distinction. No effort pin changes (USER-RESERVED). Work items: 1. **Phase-entry check** (per tracker item, before any create): ```bash gh issue list --state all --search '<key-term> in:title' --json number,title,state ``` Multi-match rule: prefer exact-title + open state; if >1 credible match remains, stop and surface for user choice. 2. Item A — effort recalibration: on match, comment linking this PLAN + the effort slice; else create (`chore: effort judgment recalibration (choosing-a-model routing vet)`) with body: effort-slice pointer, pinnable (`effortLevel` via dotfiles seam) vs session-only (top effort tier; `--effort` flag) lane distinction, USER-RESERVED marker on fleet-pin changes, task #18 link. The created-or-pivoted artifact (issue body or comment) must carry both lane labels. 3. Item B — statusline prime-drift indicator (approval-gated: files only if the approval decision confirms DEFER-to-tracker): same search-before-create shape; body records the Fable proposal + trigger (priming proves forgettable in practice). 4. Dual verification of outbound issue text (brief — single reviewer acceptable for tracker prose if the user approves the carve-out; default remains dual). 5. Local gates green (markdownlint, skill checks, script tests). 6. Close-out (full topic-docs lifecycle — prune is only safe with its pointer + graduation halves): (a) paste the approved PLAN.md + verification summary into the PR body inside `<details>` (43 KB < ~64 KB cap; the PR body becomes the durable record); (b) graduate durable outcomes through the knowledge-vault seam — apply the ADR admission test (hard to reverse + surprising + real trade-off) to candidates (e.g. the fleet-wide promotion gate, the hash doctrine); write `docs/adr/` entries only for those that pass all three; actionable follow-ups already ride the Phase 7 tracker items; (c) ONLY THEN prune `docs/topics/opus-5-prompting-interview/` in a final commit AND pointer-ize `.work/opus-5-prompting-interview/PLAN.md` to the PR body URL (deferred from Phase 1 for exactly this reason). PR sequencing: the `contract-slice-prune-gate` red-lines this slice's presence in any PR diff (slug verified absent from `scripts/contract-slice-baseline.txt`; branch-push CI green, PR CI red by design) — so EITHER open the PR only after the prune commit, OR open a draft PR early and name the expected-red gate in the PR body. Default: prune-then-PR. **Sanity Check:** - Both item numbers/URLs (created or pivoted-to) recorded in phase notes. - Item A's created-or-pivoted artifact contains `pinnable` and `session-only`. - `bash scripts/check-changed-skills.sh` (changed set) exits 0 locally before PR. ## Test strategy TDD where a deterministic surface exists; doctrine prose verified by architected independent review (dual-verifier policy), not instructed self-checks — consistent with the doctrine shipped. - **Phase 3 scan scripts** — Red-Green: fixtures first (positive: instructed self-check, don't-think, conservative-directive), then patterns. Scanner is advisory (over-produces by contract); FENCES live in criteria.md and are proven by the acceptance-run report checks (manifest-scanned-but-not-flagged assertions), not scanner tests. - **Phase 4 evals** — `evals/evals.json` encodes routing/trigger cases; schema-validated in CI; BEHAVIOR proven by Phase 6's live end-to-end run. - **Per-phase dual verification** — fresh-context Claude (high) + Codex GPT-5.6 Sol (high, text-embedded while task #15 blocks file access) on every AUTHORED artifact; mechanical copies verified by hash manifests instead (reasoned carve-out). Records: `.work/opus-5-prompting-interview/build-verification/<phase>-<artifact>-<vendor>.md`; verification records and verdicts are append-only; corrections land in the artifact. - **Static gates** — markdownlint (hygiene job), `skill-quality:check`/`skill-quality-gate` (Phase 4), `changelog-parity-gate` (all bumps), `pr-title`, `portability-lint` (Phases 2-4), `shell-portability-lint` (Phase 3 scripts), `skill-leaf-name-gate` (Phase 4), `orphaned-fixture-gate` (Phase 3 fixtures). - **End-to-end** — Phase 6 IS the e2e test of Phase 4 against a live doc. - **Empirical probes** — Phase 2's thinking-off probe (protocolized, dated observation artifact). ## Alternatives considered | Alternative | Why rejected | |-------------|-------------| | Parallel model-delta rule class in audit-instructions | Validator consensus (merged triage #5): extend I8 rows; a parallel class duplicates the model-era concept | | Two-layer pipeline: engine in `knowledge` + profile in `claude-ops` | Both Claude validators independently invoked Rule of Three; engine extraction waits for the third profile (merged triage #10, resolved in interview continuation) | | Reuse `review:fanout` for dual verification | Verified NOT reusable this session: diff-shaped pre-flight, review-specific normalization; no callable verify primitive. Borrow only the Codex-as-uncorrelated-vendor dispatch pattern | | Retire `opus-adaptation.md` outright | Content remains valid for its calibration target (Opus 4.8); the defect is version-blind routing, not the deltas. Rescoping preserves working doctrine; acceptance criterion demands only that Opus 5 never applies it verbatim | | Silently default `--target-model` from the pinned settings alias | Verified impossible: pinned value `opus[1m]` carries no version; silent aliasing would misfire the exact distinction the deliverable exists to draw — fail-loud normalization instead | | Fence false positives in the scanner | Contradicts the scanner's documented advisory contract (always exit 0, over-produce); fences owned by criteria.md, adjudicated by the model lane | | SessionStart auto-prime for the delta chapter | Deferred-with-trigger in the Brief (manual priming proves forgettable) — out of this plan | ## Risks and mitigations | Risk | Likelihood | Impact | Mitigation | |------|-----------|--------|------------| | Instruction compounding in `opus-5.md` | Med | Med | Curated-deltas contract; Phase 3 acceptance run covers the chapter (meta-surface fence keeps it a scanned-not-flagged surface) | | Harness-claim drift between corpus date and build | Med | Med | Fresh-docs mandate: fetch + cite at build; applicability tags verified at tag time | | Concurrent-branch collision on `fable-5/SKILL.md` (live `docs/ignition-rebind-note` worktree; 40+ registered worktrees) | Med | Med | Phase 2 pre-flight branch/worktree sweep; sequence or rebase deliberately | | Prompt-injected source docs steering digest/verify agents into future instruction artifacts | Med | High | Untrusted-source discipline as a named SKILL contract (content = data, never directives); dual cross-vendor verification checks fidelity against source; human approval gates on all instruction-surface commits | | Licensing/redistribution of full doc copies + 15.25 MiB PDF | Low | Med | Phase 5 licensing pre-flight; private org repo; retention terms recorded; pointer-only fallback per artifact | | Codex verifier degraded (task #15: no file access) | High | Low | Text-embedded mode (proven in validation round); noted in each record | | Verifier cost/availability (repeated high-effort cross-vendor passes) | Med | Low | Degraded-verifier fallback documented per record, never silent; batch verification per phase, not per file | | Conservative-phrasing false positives beyond known shapes | Med | Low | Two criteria-owned fences + report-only + acceptance-run negative assertions | | Cross-repo coordination (corpus PR vs plugins PR) | Low | Low | Phases independent by design; corpus graduation has no code dependency on plugin phases | | Naming tournament stalls Phase 4 | Low | Low | Seeds + shape constraint pre-fed; same-session decision | | `autoUpdate: true` feedback loop — merged artifacts become standing instructions (arm-time `opus-5.md`, live I8 rows) inside sessions still executing later phases | Low | Med | Single PR at close-out — nothing publishes mid-effort; acceptance run uses the local-path marketplace install, not a published version; condition named here as accepted | ## Blast radius MEDIUM. Plugins repo: ~26 authored/modified tracked files across 3 plugins (markdown, 2 shell scripts, manifests) — all report-only or doctrine surfaces; no hooks, no CI-workflow changes, no runtime infra. Corpus repo: ~42 files, additive-only (copies + 4 authored). Everything git-revertible. Trigger matched: "new agent-instruction rules constrain future work" (audit rows + doctrine chapter) → formal stress-test run (below). ## Stress-test summary Step 3 dual review (fresh-context Claude plan-reviewer + cross-vendor Codex GPT-5.6 Sol high, text-embedded): Claude 2 CRITICAL / 10 IMPORTANT / 5 SUGGESTION; Codex 4 CRITICAL / 25 IMPORTANT / 3 SUGGESTION. Main-thread verification confirmed both Claude CRITICALs against ground truth (stale MD5 pins — 10/11 diverged post-corrections; `opus[1m]` settings alias carries no version) plus the stale-reference, prune-gate-baseline, worktree-collision, CI-gate-coverage, and seam-contradiction findings; all confirmed findings folded into the phases above. Rejected with rationale: Codex C2 (deliverable 6 "not implemented" — the Brief itself defers execution to task #18's slice) and Codex C3's scope claim (PLAN graduation + PROCESS.md queue migration are explicitly briefed; transparency lines added instead). /devils-advocate formal pass (fresh context, post-fix): 2 CRITICAL / 2 HIGH / 3 MEDIUM / 2 LOW; all 9 verified and folded in — (1) the audit resolves surfaces from the SELECTED plugin-install cache, never the repo tree, so the acceptance run now requires the local-path marketplace install (precondition added to Phase 3, fallback documented); (2) Phase 1's pointer-ization + Phase 7's prune would have destroyed the last durable PLAN copy — close-out now carries the full topic-docs lifecycle (PR-body paste, vault graduation with ADR admission test, prune-with-pointer last); (3) branch was 8 commits behind origin/main (main's playbooks 0.5.2) — Phase 1 work item 0 rebases and re-verifies all hardcoded versions/citations; plus the changed-skill gate + line budgets, the public-repo quotation pre-flight, the autoUpdate-loop risk row, and two divergence corrections (6 verification files; reflow file is derived). Its verdict: with these fixes the plan reaches HIGH confidence; its nine ground-truth checks found zero fabrications. Iteration ceiling not hit (1 formal round; fixes mechanical, no redesign). ## Open questions None — plan approved 2026-07-26 with all recommendations confirmed: statusline prime-drift indicator DEFERRED to tracker (Phase 7 item B files it); Codex text-embedded verification CONFIRMED while task #15 open; single-reviewer carve-out for Phase 7 tracker prose CONFIRMED; knowledge-corpus PR go-ahead CONFIRMED (merge stays human). USER-RESERVED items stand: fleet effort-pin changes; committing/graduating `.work` content beyond the corpus move (interview/validation records stay untracked in `.work`). ## Handoff to implementation ### User-approval gates - Phase 5 opens a PR in `melodic-software/knowledge-corpus` (new `sources/docs/` category) — confirmed at plan approval; merge stays human. - Phase 7 files tracker items (search-before-create; multi-match stops for user choice). Item B (statusline) files only if the approval confirms DEFER. - Any fleet effort-pin change is USER-RESERVED — never executed by this plan. - `[FALLBACK — confirm or override]`: Codex verifier in text-embedded mode while task #15 open. - `[FALLBACK — confirm or override]`: single-reviewer carve-out for Phase 7 tracker prose (default stays dual if not confirmed). - Briefed exceptions (transparency): PLAN graduation to `docs/topics/` (Brief header instruction) and PROCESS.md queue migration (deliverable 3 text) — both from `.work`, both explicitly briefed. - Mid-flight pivots that change acceptance criteria: stop + replan via `/planning:plan review`. ### Execution shape ([EXEC-SHAPE] tagged) - Sequential main-session, all 7 phases. Wave-A parallelism exists (Phases 2/3/4 file-disjoint; Phase 5 repo-disjoint) but is declined: doctrine-authoring quality + shared corpus context outweigh wall-clock; token cost LOWER sequential. Phase 6's internal fan-out is the skill's own design. - Dependency edges: 1 → {2,3,4,5}; Phase 2 → Phase 3 acceptance run (clean playbooks result proves the conflict fix; REQUIRES the local-path marketplace install precondition — edge drops if the documented post-merge re-scope fallback fires); 4 → 6; 6 → opus-5.md effort cross-check (Phase 6 item 3); 6 → 7. - Per-phase routing: all main-session except Phase 6's skill-internal sub-agents. - Naming tournament at Phase 4 start (Brief deliverable text "at build" wins over the deferred-question phrasing). - Commit boundaries: ≥1 Conventional-Commits commit per phase WITH tracked changes (Phase 6 conditional); plugin version bumps ride their phase's commit. ### Mechanical work - Branch `feat/opus-5-prompting-integration` (conventional prefix; checked out). - Stage explicit paths only; never `git add -A`. - PR title Conventional Commits; body sections: Summary, Test plan, Related. - PR sequencing: default prune-then-PR (close-out prunes `docs/topics/opus-5-prompting-interview/` first; `contract-slice-prune-gate` is red on any PR diff containing the slice — slug not in the grandfather baseline). Draft-PR-with-named-expected-red is the documented alternative. - Sequential fallback: n/a (sequential by design). If a future session parallelizes 2/3/4, the per-phase file tables are the scope fences; PLAN.md edits stay main-session. </details> **Verification records** (local-only, git-ignored `.work/opus-5-prompting-interview/build-verification/`): `phase2-opus-5-chapter-claude.md`, `phase2-opus-5-chapter-codex.md`, `thinking-off-probe-2026-07-26.md`, `phase3-audit-instructions-claude.md`, `phase3-audit-instructions-refuter.md`, `phase3-acceptance-run-2026-07-26.md`, `phase4-docpage-digest-claude-verifier.md`, `phase4-docpage-digest-adversarial-refuter.md`, `phase5-precopy-manifest-opus-5-prompting.txt`, `phase5-postcopy-manifest-opus-5-prompting.txt`, `phase5-precopy-manifest-opus-5-system-card.txt`, `phase5-postcopy-manifest-opus-5-system-card.txt`, `phase5-provenance-artifacts-claude-verifier.md`, `phase5-provenance-artifacts-adversarial-refuter.md`, `phase6-effort-pipeline-run-2026-07-27.md`. Where the cross-vendor Codex verifier was unavailable, the degraded fallback (same-vendor adversarial refuter, or text-embedded mode) is recorded in the verdict header — never silent. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…or a non-repo consuming directory (#1728) ## Summary `continue-in-background`'s dirty-tree gate opened by running `git status --porcelain -uall` in the consuming project. In a directory that is not a git repository — a session started in `$HOME`, say — that fails with `fatal: not a git repository` and the skill has no specified behavior. The gate specified clean, dirty, and linked-worktree; not "no repository at all". The gate now establishes repository status first with `git rev-parse --is-inside-work-tree`, and is exhaustive **by construction** rather than by enumeration: two results may leave the default, and everything else falls through to the conservative branch. | `rev-parse` result | Behavior | | --- | --- | | prints `true` | Inspect the tree with the existing `git status --porcelain -uall` gate, unchanged | | fails *specifically* with "not a git repository" | Launch. No uncommitted work to protect, and no worktree isolation to lose — outside a repository (absent a `WorktreeCreate` hook) background sessions write to the working directory directly. The launch report states that reading | | **anything else** | Tree state UNKNOWN, which is not clean → do NOT launch; same fallback as the dirty case | That third row is the load-bearing part, and it is why this is a little more than the issue's "one or two sentences" — not scope drift. A gate that fails open is worse than no gate. Reading a non-zero exit alone as "no repository" would put dubious-ownership, damaged-repository, and git-missing cases on the launch path — exactly where the tree is most likely dirty and least likely readable. The unknown default is deliberately wide and it catches a zero-exit case too (below). Also here: the context-gathering block's "treat any failure as an unknown value and carry on" is now scoped to itself. It colors the save-point and is not the gate; carrying that shrug — or that block's non-`-uall` `git status` output — into delivery step 1 would defeat the gate from a section that runs before it. ## Evidence **Gates** (run in the worktree against `origin/main`): - `check-skill` (the checker `scripts/check-changed-skills.sh` invokes): **PASS — 0 errors, 0 warnings**; 195/500 lines, all 4 base-ref trigger phrases preserved - `scripts/validate-plugin-contracts.mjs`: **pass** — 43 setup skills, 2123 plugin files - `scripts/check-changelog-parity.sh --check-bump origin/main`: **pass** — 0.17.16 → 0.17.17 patch bump paired with its `## [0.17.17]` entry - `markdownlint-cli2` on both changed markdown files: **0 errors** - `evals.json` validated against `plugins/skill-quality/reference/evals.schema.json`: **valid** **Harness claim verified against current docs.** The non-repo sentence asserts harness behavior, so it was checked against <https://code.claude.com/docs/en/agent-view> this session rather than from recall. That page states isolation is skipped when the working directory is not a git repository and no `WorktreeCreate` hook is configured, and that outside a repository sessions write to the working directory directly — which is what the new branch relies on, including the hook qualifier. **Non-vacuousness — stated honestly.** `evals.json` in this repo is declarative and model-graded; there is no runner that asserts, so the three added cases are not executed regression tests and are not presented as such. The discriminating argument is textual and checkable from the diff: an agent following the pre-change SKILL.md has no branch for #5 (it runs `git status --porcelain -uall` blind and hits `fatal: not a git repository`) and no branch at all for #6 or #7. - **#5 `non-repo-directory-launches`** — non-repo consuming directory → launches, states the non-repo reading, STOPS - **#6 `unknown-tree-state-does-not-launch`** — dubious-ownership failure → does NOT launch. This is the case that proves the gate does not fail open - **#7 `no-work-tree-despite-zero-exit-does-not-launch`** — bare repository, exit 0 printing `false` → does NOT launch ## Review Reviewed by a fresh-context reviewer with the rationale withheld. Two IMPORTANT findings, both fixed in `748ab3cb` before this PR: 1. **Unrouted fourth outcome.** `git rev-parse --is-inside-work-tree` exits **0** and prints `false` inside a bare repository or a `.git` directory — verified empirically by the reviewer. The original three-way enumeration left that state unspecified, which is the same defect class the issue reports. Fixed by inverting the structure to two specified results plus a default, and guarded by eval #7. 2. **Contradiction with the context block.** "Treat any failure as an unknown value and carry on" sat 50 lines above a gate that now reads a git failure the opposite way. Fixed by scoping that sentence to its own block and pointing at the gate as owning failure semantics. One finding was accepted and **not** fixed, as out of scope: the gate's pre-existing rationale that uncommitted changes "would NOT carry into the launched agent's edits" does not hold when a consumer sets `worktree.bgIsolation: "none"`, under which background sessions edit the working copy directly. The gate's decision stays conservative either way, so this is an inaccurate rationale rather than a hole — untouched by this PR and worth its own issue. Closes #929 ## Related - #924 — introduced the skill and this dirty-tree gate - #233 — origin design for the save-point/handoff engine the skill shares - #1687 — the `$`-expansion isolation constraint the context block's shape exists to satisfy; the new `git rev-parse --is-inside-work-tree` carries no `$`-expansion and sits in the body, not pre-compute --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…oring time (#1751) No linked issue ## Summary The `pr-issue-linkage / pr-issue-linkage` check is a **required** merge gate, but nothing enforced its contract at the moment a PR body was written. A body missing a closing keyword or a `## Related` section was therefore only ever caught post-hoc — one CI round trip after the PR was already open — which is what happened on most PRs filed directly with `gh pr create` during the 2026-07-29 queue drain. This adds the missing authoring-time enforcement: a `PreToolUse` hook on the Bash tool, owned by the `source-control` plugin, that validates a `gh pr create` / `gh pr edit` body against the same contract **before** the call runs and blocks with the missing half named, so the authoring agent self-corrects in the same turn instead of on the next CI cycle. `/source-control:pull-request create` has always run the equivalent pre-create gate (`skills/pull-request/reference/create.md` §2.4.2). This hook covers the calls that never go through the skill; the skill's own path is unaffected, since its gate runs first and the hook then sees a body that already passes. ### Enforcement is keyed to the consumer's own policy The gate runs only when the repository root carries `.github/workflows/pr-issue-linkage.yml` (or `.yaml`). A repository that does not run the check is never gated, so the hook cannot drift away from what its consumer actually enforces. This is deliberately **not** the `pr_body_required_sections` seam (`docs/conventions/pr-body-convention/`). That key is the repo's configurable section scaffold, and its portable default excludes `Related` on purpose; the authority for *this* gate is the workflow file that defines the check. ### The validator is mirrored, not approximated Ported from the reusable `melodic-software/ci-workflows/.github/workflows/pr-issue-linkage.yml` `github-script` step, including the three places a hand port silently diverges: - **Both HTML-comment strips, in order** — every terminated comment span, then an unterminated comment opener swallowing the rest of the body. Without this an unedited PR template, whose instructional prose names the very markers the gate looks for, passes vacuously. - **Heading-level semantics** — only a heading at the same level or higher closes `## Related`, so a nested `### ...` subsection is that section's *content*. A naive "next line starting with `#`" reading calls such a section empty and false-blocks a compliant body. - **JavaScript word boundaries**, which POSIX ERE has no equivalent for, transcribed as explicit non-word characters around a newline-wrapped probe — so `Closes #12abc` and `unclosed #5` stay non-matches exactly as they are in CI. ### Fail-open on extraction, fail-closed on a determinable bad body Judged: a `--body`/`-b` literal, a readable `--body-file`/`-F` path, and the sole heredoc feeding `--body-file -` or a `--body "$(cat <<EOF ... EOF)"` substitution. Allowed: an unexpanded variable, several heredocs (which one reaches `gh` is not statically knowable), an unterminated heredoc, an unreadable body file, an absent body flag (`--fill`, `--template`, `--editor`, the interactive prompt), and any `--repo`-targeted invocation, whose target may not be the repository whose workflow file the scope guard read. Guessing at a body the hook cannot see would block compliant calls, which costs more than a miss. The PowerShell tool and direct `gh api .../pulls` calls are documented as out of scope at the hook's own site, alongside the `--repo` limit. ## Test plan - `plugins/source-control/hooks/pr-body-linkage-gate.test.sh` — 53 black-box cases, all passing: the scope guard, both halves independently, all nine closing keywords plus the colon and `owner/repo#N` forms, both no-issue markers, the two word-boundary non-matches, three comment-stripping cases, four section-boundary cases (including the deeper-subsection case), every body source and every undeterminable-body path, `gh pr edit`, env/`env(1)`/`sh -c` wrappers, `--repo`, and the kill switch. - Repo gates run locally, all green: `shellcheck` (with `.shellcheckrc`), `shfmt`, `check-silent-skips`, `check-hook-userconfig-argv`, `check-shell-portability` (vs `origin/main`), `check-cross-plugin-source-drift`, `sync-hook-utils --check`, `check-changelog-parity` (`--check` and `--check-bump`), `check-plugin-manifest-presence`, `validate-plugin-contracts`, `validate-plugins`, and `markdownlint-cli2` on every changed markdown file. - Dogfooded: this PR's own body was run through the hook before `gh pr create` fired — and the first draft was **blocked**, correctly. That draft spelled the comment delimiters out literally while describing the comment-stripping rule, so the strip ate everything after them, `## Related` included. CI would have rejected it identically. The hook caught it before the PR existed, which is the whole point. ## Related - Refs #1748, #1745, #1708 — PRs whose bodies failed `pr-issue-linkage` post-hoc during the 2026-07-29 queue drain, which is the recurring failure this hook removes at the source. - `docs/conventions/pr-body-convention/README.md` reserves the enforcement seam for the `pr_body_required_sections` key; this hook deliberately does not consume that key, for the reason given under "Enforcement is keyed to the consumer's own policy" above. - `plugins/guardrails/hooks/block-convention-violation.sh` gates the `gh pr create` **title** against the tracked team convention. Different field, different source of truth; the two hooks compose rather than overlap. --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…1753) No linked issue ## Summary An independent fresh-context review of #1751 — run after that PR had already merged — found six defects in the `pr-body-linkage-gate` hook. I reproduced every one before touching the code; all six are fixed here, with a regression case for each. Two of them were live in normal use, which is why this is going out immediately rather than as routine follow-up. ### The two that were biting **A `cd` on the same command line retargeted the whole gate.** The gate file and any relative `--body-file` resolve against the hook payload's `cwd`, but the segment tokenizer discards the `cd` segment — so `cd <worktree> && gh pr create …`, a routine shape in a multi-worktree setup, was judged against the session's directory instead of the one `gh` actually runs in. Two distinct live defects fell out of that: - a **false block** — a compliant body was rejected because a same-named file in the session's directory was read in its place; - a **scope leak** — enforcement fired inside repositories carrying no `pr-issue-linkage.yml` at all, directly contradicting the scope guard's own stated promise. A `cd`, `pushd`, or `popd` segment now puts every later segment out of scope, the same posture `--repo` already had. A directory change *after* the `gh` call still gates normally. **The hook exceeded its own timeout on large bodies and silently stopped gating.** Trimming each body line ran through a command substitution, so every line cost a fork. Measured before the fix: | body | before | after | |---|---|---| | 200 lines | 4.4 s | 0.6 s | | 500 lines | 10.4 s | 0.7 s | | 1000 lines | 18.3 s | 1.3 s | | 5000 lines | — | 1.3 s | `hooks.json` declares a 15-second timeout, so past roughly 800 lines the hook was cancelled — on exactly the large PRs it most wants to catch, and `## Related` being the last section means the scan always walks the whole body. Both per-line trims plus the one in the heredoc reader are parameter expansion now, which is why the curve goes flat. A regression case fails if a 1000-line body ever approaches the timeout again. ### The other four - **Locale-dependent verdicts.** `[[:space:]]` stood in for JavaScript's `\s`, but its membership is locale-defined while `\s` is a fixed set. Under `LC_ALL=C` a body with a non-breaking space between `Closes:` and `#5` — routine in text pasted from an issue title — was rejected where CI accepts it. Both halves are pinned now: every non-ASCII member of the `\s` set is rewritten to a plain space by UTF-8 byte sequence (spelled as bytes, not `\uXXXX`, because bash renders `\u` through the very charmap being removed as a dependency), then matching runs under `LC_ALL=C` where `[[:space:]]` is exactly the six ASCII characters. Tests assert both locales agree. - **pflag grouped shorthand bypassed the gate.** `gh pr create -db BODY`, `-dbBODY`, `-dF file`, and `-dFfile` are all valid gh and all passed, because only a bare `-b`/`-F` was recognized. Clusters are walked properly now; an unknown letter stops the walk rather than guessing which letter would have consumed the next word. - **`gh` was matched only as the exact literal**, so `gh.exe`, `/usr/bin/gh`, `./gh`, and `sudo gh` all bypassed it — inconsistent with the basename comparison the wrapper loop ten lines above already used. Matched by basename now, backslash paths and `.exe` included. - **A stalled payload blocked the command.** The gate inherited the sibling *security* guards' fail-closed posture on unreadable stdin, which for a scoped policy gate means refusing an arbitrary Bash command because the hook could not read its own input. It allows now, with the divergence and its reason recorded at the site. Two smaller things came along: the absent-versus-empty `## Related` distinction moved off a sentinel string a section's content could theoretically equal, onto the return-code channel; and the pre-filter now requires `gh` at a word boundary, so `npm run lighthouse-prod` no longer pays for a full parse. ### What I did not fix One comment-stripping residual stays, documented at the hook's own site: the validator strips a comment span across a line break and joins what surrounds it, so a heading split by a comment mid-word is one heading to CI and two lines here. Reproducing it needs whole-body rather than per-line stripping, and the shape does not occur in a real body. ## Test plan - `plugins/source-control/hooks/pr-body-linkage-gate.test.sh` — **92 cases, up from 57**, all passing. New coverage is exactly the reviewer's uncovered list: grouped shorthand in all four shapes, `cd`/`pushd` drift plus the after-the-call control, `gh.exe` / path-qualified / `./gh` / `sudo gh`, a 1000-line body timing guard, locale-pinned cases run under both `LC_ALL=C` and a UTF-8 locale, `--body-file=X` and `-FX` attached forms, an absolute body-file path, the `.yaml` gate spelling, `gh pr edit --body-file`, missing-`jq` fail-open, and CRLF bodies. - Every defect reproduced against the shipped 0.37.0 hook first, then re-run against the fix. The before/after numbers in the table above are from that harness. - Differential re-run against the real ci-workflows validator: 46 fixtures, 46 agree, 0 disagree — unchanged, confirming none of these fixes moved the validator parity. - Repo gates green locally: `shellcheck`, `shfmt`, `check-silent-skips`, `check-hook-userconfig-argv`, `check-shell-portability` vs `origin/main`, `sync-hook-utils --check`, `check-changelog-parity --check-bump`, `validate-plugin-contracts`, and `markdownlint-cli2`. ## Related - Follows #1751, which introduced the hook. These are review findings against that PR; it had already merged when the review returned, so they land as a fix rather than as changes on that branch. - The test suite drops its claim to "prove the hook mirrors the ci-workflows validator". Nothing in it executes that validator — all 92 expectations are hand-transcribed from a reading of the JavaScript, which is precisely how the locale divergence survived #1751's own review. A genuine oracle would mean vendoring upstream JavaScript into this repo, which needs a sync seam decision rather than an invented one; recorded here as a follow-up candidate, deliberately not filed. - `docs/conventions/pr-body-convention/README.md` — unchanged by this PR; the gate still keys on the workflow file rather than the `pr_body_required_sections` key, for the reason #1751 recorded. --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…onomy (#2005) ## Summary Alignment change set from the full `/knowledge:youtube-digest` of **Boris Cherny: "We Cut 80% of Claude Code's Prompt"** (YC Startup School, 2026-07-25). Research record + prioritized menu live in `melodic-software/knowledge-corpus` PR #10 (slice `boris-cherny-we-cut-80-of-claude-code-s-qyPCVqFUyDo`). **Repo alignment (menu P0 items):** - `docs/PLUGIN-PHILOSOPHY.md` — new **Instruction economy** section: per-session-tax framing, evidence-gated additions ("stumble twice" before any new standing instruction), generation-triggered ablation, evals-outlive-instructions, the official durable-tier carve-outs (deterministic policy hooks, team conventions in git), explicit security non-relaxation (injection-resistance claims are hedged in primary sources), and the note that verification-first task design is already encoded by the `verification`/`planning`/`tdd`/`testing` plugins. **Downstream-consumer capability (menu #2):** - New **`claude-config:unhobble`** skill (`0.22.0`) — the empirical bare-baseline experiment consumers run on their own repos: snapshot + policy-vs-behavioral classification → reversible strip on a dedicated branch → stumble ledger across fresh sessions → evidence-gated re-add citing ledger rows. Managed settings and policy hooks are never stripped; `CLAUDE_CODE_SIMPLE` explicitly out of contract (undocumented). 8 evals; `check-skill.sh` PASS (0 errors, 0 warnings, description 641/1536); `audit-instructions` gains the reciprocal route-out. **Verification:** two fresh-context reviewer agents (skill-quality contract; research-fidelity vs the slice's RESEARCH.md) — all findings fixed (skill count phrasing, blog citation + "coding evaluations" qualifier, reciprocal routing, description trim). **Deliberately deferred** (tracked in the slice's `recommendations/`): skill-authoring playbook echoes of the evidence gate (avoids doc duplication — the instruction-economy rule itself argues against second copies), listing-budget program (menu #4, needs operator decision), hook-surface policy-vs-behavioral classification sweep (menu #5), marketplace self-maintenance routines (menu #9), recurring work-item wiring for the ablation cadence (menu #1 second half). No linked issue ## Related - Research substrate: melodic-software/knowledge-corpus#10 - Talk: <https://www.youtube.com/watch?v=qyPCVqFUyDo> · YC Root Access recap: <https://www.ycrootaccess.com/p/boris-cherny-building-claude-code> - Official doctrine: <https://code.claude.com/docs/en/best-practices> (fetched 2026-08-08) 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
<!-- CURSOR_AGENT_PR_BODY_BEGIN --> Fixes #1290 ## Summary Two concurrent attended sessions on one repository could both surface and mutate the same row because `/work-items:attend-queue` had no claim protocol while `/work-items:work` already used the seam assignee + lease (`exit 7` → advance). Documents the same seam claim protocol `work` uses, scoped to attend-queue row disposition: claim before mutate, release before flip to autonomous-eligible, session-start reclaim, binding routing. Bumps `work-items` to **0.35.16**. ## Test plan - [x] Eval #5 covers concurrent-session exit-7 skip behavior - [x] Single-session run needs no new required argument ## Related - #1290 - Unblocked by #1295 / #1841 <!-- CURSOR_AGENT_PR_BODY_END --> <div><a href="https://cursor.com/agents/bc-8279724f-c3b6-4e4f-be24-3dcf28782ae1?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a> <a href="https://cursor.com/background-agent?bcId=bc-8279724f-c3b6-4e4f-be24-3dcf28782ae1&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a> </div> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Kyle Sexton <kyle-sexton@users.noreply.github.com>
What
A versioned, marketplace-wide hook-telemetry contract (a public API for plugin hooks to emit structured execution telemetry) plus
markdown-formatteras its first producer. A hook emits one JSON envelope per run to a consumer-set sink (HOOK_TELEMETRY_SINK, fire-and-forget); unset → no-op. The signal it carries — this hook's ownduration_ms, outcome, findings — is what Claude Code's native OTEL cannot provide (CC reports an aggregatetotal_duration_msand excludes third-party plugin content).Contents
docs/conventions/hook-telemetry/): envelope + per-hookdataJSON schemas, CHANGELOG, worked example.schema_version1.0.markdown-formatter):hook::emit_telemetryemits the envelope after formatting; relativeHOOK_TELEMETRY_SINKresolved producer-side against the caller's repo root (clone-portable, worktree-safe; works around CC #9447 emptyCLAUDE_PROJECT_DIRin plugin hooks).hook-utils27/0,markdown-format41/0.Design notes
statusis a documented open string, not a closed enum — a closed JSON-Schema enum would reject a future value, contradicting the contract's own "consumers MUST tolerate unknown values" rule (JSON Schema 2020-12 §6.1.2). Mirrorshook_eventand OpenTelemetry's open-enum pattern (error.type).stdout+stderr→/dev/null) — never blocks the hook, never touches itsadditionalContextchannel.Validation
.mdedit produced a telemetry record with an isolated per-hookduration_msand a repo-relative subject; fire-and-forget non-blocking and child-survives-reaping both confirmed live (plain&, nosetsidneeded).main(ci: onboard to the CI platform (ci-workflows + standards) #4 CI platform) and conforms to its lanes (shellcheck, exec-bit, typos all clean locally).Notes for reviewers
Consumer (sink) wiring is per-repo: a consumer sets a relative
HOOK_TELEMETRY_SINKin itssettings.jsonpointing at a script that maps the envelope into its own store. No consumer repo is named in the contract (platform stays decoupled from consumers).