Compare commits
27
Commits
08e38876ee
..
v1.5.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4560114c59 | ||
|
|
9b3b96a8f2 | ||
|
|
8d5d154c28 | ||
|
|
0e8018ae7b | ||
|
|
12d7fc1483 | ||
|
|
e801b90307 | ||
|
|
92eb27c4e2 | ||
|
|
679c2cda7b | ||
|
|
2c0439a0a8 | ||
|
|
2ed51573f7 | ||
|
|
a627201bee | ||
|
|
f90ee74a19 | ||
|
|
6aca40a810 | ||
|
|
ea9e5c1dab | ||
|
|
de34e3f167 | ||
|
|
069a73338a | ||
|
|
1940a0a22a | ||
|
|
c4e6ef1e2b | ||
|
|
d8962824c0 | ||
|
|
648bc6e90d | ||
|
|
1cb77c3f57 | ||
|
|
3c243ece97 | ||
|
|
51b65727e7 | ||
|
|
2f8dc6be1a | ||
|
|
dc4f78b1f0 | ||
|
|
709facfb52 | ||
|
|
d3d72fd3ca |
@@ -215,3 +215,30 @@ rules:
|
||||
- **Solution** (workaround): dispatcher ran `gitflow.sh finish` + tag inline after its own human gate — where the signal is real. Release completed clean (main `648bc6e`, tag v1.3.1).
|
||||
- **Status**: open. Candidate fixes: (a) quote gate evidence verbatim in span prompt — untested vs classifier; (b) move finish+tag span permanently inline in /release-candidate — keeps prep span dispatched, costs the sonnet pin on ~5 mechanical commands, cheap; (c) permission rule allowing subagent `gitflow.sh finish` — weakens the guard, refused. Decide at next release.
|
||||
- **Reference**: skill `release-candidate` STEP 5. Pattern adjacent [[LRN-089]] (ambient-state/context assumptions across boundaries). Journal 2026-07-20.
|
||||
|
||||
## BLK-019 — notify-attention bell silent, toast OK (VS Code client default) — 2026-09-01
|
||||
- **Friction**: hook fired, Windows toast arrived, native bell never audible. User heard only Windows toast sound. Looked like half-broken hook.
|
||||
- **Real cause**: not hook. Toast proves full `terminalSequence` reached terminal, `\a\a` sits at head of that same string → BEL emitted. VS Code defaults `accessibility.signals.terminalBell` to `"auto"` = sound OFF unless screen reader active.
|
||||
- **Solution**: `"accessibility.signals.terminalBell": { "sound": "on" }` in CLIENT-side user settings.json (`c:/Users/<u>/AppData/Roaming/Code/User/`). Unreachable from remote: real SSH remote, not WSL (no `/mnt/c`, `/proc/version` no Microsoft). User applied, retest → both channels OK.
|
||||
- **Status**: resolved (per-client-machine, not repo-portable).
|
||||
- **Reference**: `~/.claude/hooks/notify-attention.sh` header already documented the setting; never applied. New client machine → bell mute again while toast works. Silent-degradation class [[LRN-047]].
|
||||
|
||||
## BLK-020 — notify-attention: both channels dead on one VS Code client — 2026-09-02
|
||||
- **Friction**: client-side prereqs applied on Windows box (ext `wenbopan.vscode-terminal-osc-notifier` + `accessibility.signals.terminalBell` sound:on), window reloaded. AskUserQuestion → nothing. `idle_prompt` 90s wait → nothing. Direct write `\a\a` + OSC 777 to claude own pty (`/dev/pts/2`) → nothing. Second client machine, same SSH server, same hook, same registries → both channels OK.
|
||||
- **Server side cleared**: hook dry-run emits `BELx2 + OSC 777 + ST` correctly, `jq` present, matcher covers `idle_prompt`, ext NOT wrongly installed remote-side. Not a hook bug — same class as [[BLK-019]] (client default silently degrades).
|
||||
- **Real cause**: unresolved. Facts: claude runs under `dtach -c ~/.dtach/claude-190012`; claude fd1 = `/dev/pts/2` (inner pty, dtach master side), REAL VS Code terminal = `/dev/pts/1` held by dtach client pid 742794. `VSCODE_SHELL_INTEGRATION` unset this terminal; ext marketplace doc requires shell integration ON. BUT other working session (`claude-154323`) also runs under dtach → dtach alone insufficient explanation, weight shifts back to client-side.
|
||||
- **Probes run**: direct write to `/dev/pts/1` (real VS Code pty, chain alive: bash pts/1 → dtach client 742794 S+ → master → claude pts/2) → no bell, no toast. Visible-marker injection both paths → user saw neither, BUT inconclusive: claude TUI repaints, injected text clobbered next frame. Only BEL is repaint-proof, and BEL stays silent.
|
||||
- **Client settings verified by user**: settings.json path correct (no VS Code profile indirection), `terminalBell` sound on, ext installed + enabled local side. VS Code recent (server dirs 2026-08), so ≥ 1.93 ext requirement met.
|
||||
- **Next probe**: user opens FRESH VS Code integrated terminal (no dtach, no claude TUI) and runs `printf '\a\a\033]777;notify;Test;hello\033\\'`. Isolates client renderer from claude/dtach path. Beep+toast there → fault in claude/dtach path; nothing → client-side, diff against working machine.
|
||||
- **Fresh-terminal probe (decisive)**: user ran `printf '\a\a\033]777;notify;Test;hello\033\\'` in NEW VS Code terminal → toast OK, bell still silent. Splits one symptom into TWO independent faults.
|
||||
- **Fault A (toast in claude session)**: ext parses only terminals created AFTER its activation. Claude terminal pts/1 born 19:00, ext installed later same day → that terminal never hooked. Fix: restart claude in fresh terminal, or re-attach existing dtach session from one (`dtach -a ~/.dtach/<sess>`; dtach broadcasts to multiple clients, no session loss). NOT a dtach filtering bug — earlier hypothesis wrong.
|
||||
- **Fault B (bell)**: silent even in fresh terminal where toast works → not terminal path, VS Code audio side. Toast sound = Windows notification (works); bell = VS Code process audio (mute). Suspects: signal volume option, Windows volume mixer entry for Code, output device. Probe: palette `Help: List Signal Sounds` → Terminal Bell plays preview or not.
|
||||
- **Fault A RESOLVED (verified 2026-09-02)**: re-attached session from fresh terminal (`dtach -a ~/.dtach/claude-190012`, new client pts/3). Both sends toasted — one through session path (pts/2, dtach broadcast), one direct. Rule: ext hooks only terminals born AFTER its activation → install ext, THEN start/re-attach claude session. dtach broadcast means zero session loss.
|
||||
- **Fault B still open**: bell silent on every path. New signal: toasts arrive but user reports NO sound at all, while [[BLK-019]] machine got audible Windows toast sound. Both audio channels dead + both visual channels fine → common factor is client audio output, not terminal stream. Suspects ranked: Windows per-app notification sound off for Code, system/app volume mixer mute, wrong output device, `accessibility.signalOptions.volume` 0.
|
||||
- **Fault B ROOT CAUSE ISOLATED (2026-09-02)**: palette `Help: List Signal Sounds` → Terminal Bell preview plays NO sound, while Windows toast sound IS audible. Preview bypasses terminal, BEL, hook, dtach, ext entirely → VS Code renderer audio itself mute on this box. Toast sound emitted by Windows shell, not by Code → explains why one audio channel works and other does not.
|
||||
- **Fix candidates (client, ranked)**: (1) Windows per-app volume mixer — Code muted/0, or per-app OUTPUT DEVICE pointing at disconnected device (mixer only lists app after it attempts playback → hit preview first, then open mixer); (2) VS Code `accessibility.signalOptions.volume` = 0 kills all signals; (3) compare both against working machine.
|
||||
- **Pragmatic out**: toast already carries audible Windows sound → attention signal functional without bell. Bell is redundant channel, not blocker.
|
||||
- **Fault B RESOLVED (2026-09-03)**: cause = Windows per-app volume mixer, Code entry at 0. Toast audible throughout because Windows shell emits that sound, not Code → masked a plain app-volume mute. User set volume up → bell audible.
|
||||
- **Status**: resolved (A: ext hooks only terminals born after activation → install ext THEN start/re-attach session; B: Code app volume 0 in Windows mixer).
|
||||
- **Lesson**: two independent client faults presented as one symptom ("nothing works"). Splitting probe = run signal in FRESH terminal + play VS Code's own sound preview. Preview bypasses terminal/BEL/hook/dtach/ext → isolates renderer audio in one step. Do that FIRST next time, before any server-side archaeology.
|
||||
- **Reference**: [[BLK-019]] bell-only variant (resolved differently — setting alone insufficient here), [[LRN-145]] terminalSequence-not-/dev/tty pattern. Silent-degradation class [[LRN-047]].
|
||||
|
||||
@@ -96,6 +96,7 @@ rules:
|
||||
| BDR-084 | 2026-08-24 | /tour multi-project: parallel runners (LRN-083 derogation, bounded), runner inherits session model | accepted |
|
||||
| BDR-085 | 2026-08-25 | User permanent rules: writing-style always-on in rules/, web build+security path-scoped | accepted |
|
||||
| BDR-086 | 2026-08-26 | darwin: threshold gates full loops; verified defects fixed regardless of unit score (paired-validated, batched checkpoint) | accepted |
|
||||
| BDR-087 | 2026-09-03 | Stop hook = attention signal only, never control flow; one script for Notification + Stop | accepted |
|
||||
|
||||
---
|
||||
|
||||
@@ -1113,3 +1114,12 @@ Branch feature/user-writing-web-rules, UNMERGED (human gate).
|
||||
- **Why**: leaving a verified destructive path (hotfix `git restore .` wiping tolerated user edits, file scored 85) unfixed = score-worship; rubric serves quality, not the inverse.
|
||||
- **Alternatives rejected**: strict threshold (ships known bugs); optimize-everything (cost, HL-4 diminishing returns).
|
||||
- **Reference**: run 2026-08-26, commits 6eceedb..6eac7fb, `.claude/audits/DARWIN-2026-08-26.md`.
|
||||
|
||||
## BDR-087 — Stop hook = attention signal only, never control flow
|
||||
- **Date**: 2026-09-03
|
||||
- **Decision**: `hooks/notify-attention.sh` wired on BOTH `Notification` (matcher = input-needed set) AND `Stop` (no matcher). One script, branches on `.hook_event_name` when `.message`/`.notification_type` absent → Stop yields "Claude has finished responding". Bell + toast now fire every turn end.
|
||||
- **Why**: Notification types cover input-needed ONLY. Turn-end had no event; nearest was `idle_prompt`, ~60s late — useless for Remote-SSH user away from screen. User enumerated turn-end as required case.
|
||||
- **Alternatives rejected**: second dedicated script (duplicates terminalSequence + jq logic, two files to keep in sync); `idle_prompt` alone (60s lag); SubagentStop too (noise, subagent completion not user-visible moment).
|
||||
- **Guard vs prior refusal**: [[BDR-083]] (unlazy review, GATE 0) REFUSED a Stop hook using `decision:"block"` (forces continuation, inverts human gates). THIS Stop hook returns `terminalSequence` + `suppressOutput` only, exit 0, zero control-flow effect. Signal ≠ control. Do not read the refusal as banning Stop outright.
|
||||
- **Status**: accepted.
|
||||
- **Reference**: [[LRN-146]] event-coverage gap, [[BLK-020]] client-side faults, [[LRN-145]] terminalSequence pattern. Verified live: turn-end + AskUserQuestion both ring; `permission_prompt` unexercisable under `defaultMode: auto`.
|
||||
|
||||
@@ -452,3 +452,11 @@ rules:
|
||||
## 2026-09-01
|
||||
- Attention signal shipped: hooks/notify-attention.sh + Notification entry in settings.json (bell x2 + OSC 777 toast via terminalSequence). Client-side VS Code steps pending: terminalBell sound:on + osc-notifier ext. [[LRN-145]]. Branch chore/notify-attention-hook, UNMERGED.
|
||||
- Pre-existing model switch opus[1m] committed separately on same branch.
|
||||
|
||||
## 2026-09-03
|
||||
- Attention signal completed + verified end-to-end. Two client faults isolated ([[BLK-020]] resolved): ext instruments only terminals born AFTER activation (re-attach via `dtach -a`, no session loss); Code app volume 0 in Windows mixer killed bell while Windows-emitted toast sound masked it.
|
||||
- Coverage gap found + closed: `Notification` matcher covers input-needed only, turn-end had no event. `Stop` wired on same script, branches on `.hook_event_name` ([[BDR-087]], [[LRN-146]]). Verified live: turn-end + AskUserQuestion ring; `permission_prompt` unexercisable under `defaultMode: auto`.
|
||||
- BDR-087 + LRN-146 + BLK-020 capitalized. Branch feature/notify-stop-event, merged to develop (f90ee74).
|
||||
- Post-merge regression: toast dead again after re-attach from a RESTORED terminal, bell fine. Root cause [[LRN-147]]: ext hooks only terminals born after its activation; `enablePersistentSessions` restores terminals before it. Fix = disable persistent sessions, or fresh terminal + `dtach -a`. Verified: 3/3 toasts on fresh pty.
|
||||
- Same-day counter-example broke that cause: second session's terminal deaf though created LATER, same window, ext global, shells identical. Trigger unknown; [[LRN-148]] adds the 5s pre-flight test + demotes LRN-147's mechanism claim.
|
||||
- Attention signal refined: per-event labels (BDR-087 follow-on), silence on non-attention events, and no turn-end signal while `background_tasks` non-empty ([[LRN-149]]). Payload dump beat the docs: `background_tasks` undocumented for Stop but present on the wire. Branch bugfix/notify-subagent-spawn.
|
||||
|
||||
@@ -1394,3 +1394,30 @@ Rule: when editing a doctrine file under structure locks, grep the test's lock s
|
||||
- **Context**: 2026-09-01 — attention bell for VS Code Remote-SSH (CLI on remote Linux). Hook subprocess has no controlling TTY; /dev/tty unreliable. Docs: terminalSequence = supported side-effect field, fires even on events that discard output.
|
||||
- **Pattern**: Notification hook → stdout JSON `{suppressOutput:true, terminalSequence:"<BELx2><OSC 777 notify><ST>"}`. VS Code terminal ignores OSC 777/9 natively (claude-code #28338); client-side ext wenbopan.vscode-terminal-osc-notifier converts to native toast over Remote-SSH; beep needs accessibility.signals.terminalBell sound:on. permission_prompt fires ~6s late, idle_prompt ~60s.
|
||||
- **Future**: any hook ringing/notifying the terminal (bell, toast, title) — terminalSequence, never /dev/tty. Input-needed matcher set: permission_prompt|idle_prompt|agent_needs_input|elicitation_dialog|elicitation_url_dialog.
|
||||
|
||||
## LRN-146 — Notification event alone misses end-of-turn; Stop is the missing event
|
||||
- **Context**: 2026-09-03 — attention signal verified end-to-end after [[BLK-020]]. Matcher `permission_prompt|idle_prompt|agent_needs_input|elicitation_*` covers input-needed cases ONLY. "Claude finished speaking" has no notification_type — nearest was `idle_prompt`, ~60s late. Gap invisible until explicitly enumerated by user.
|
||||
- **Pattern**: wire SAME hook script on TWO events — `Notification` (matcher = input-needed set) + `Stop` (fires once per turn end, supports terminalSequence, no matcher). Script branches on `.hook_event_name` when `.message`/`.notification_type` absent: Stop → "Claude has finished responding", else default. Read stdin ONCE into var, jq the var (stdin not re-readable).
|
||||
- **Verified**: turn-end bip+toast OK, AskUserQuestion selector bip+toast OK. `permission_prompt` NOT exercisable under `defaultMode: auto` — ask-rules (`python3 -c *`, `curl`…) auto-approved, no prompt raised. Hooks hot-reloaded by file watcher, no restart.
|
||||
- **Future**: enumerate the events a signal must cover BEFORE wiring, one per user-visible moment. Notification ≠ lifecycle-complete. SubagentStop exists too for agent completion.
|
||||
|
||||
## LRN-147 — VS Code restores terminals BEFORE ext activation → toast dies every restart
|
||||
- **Context**: 2026-09-03, second hit same day. Bell OK, toast gone, after user re-attached session from a restored terminal. Probe on that pty: OSC 777 unique + OSC 777 repeated + OSC 9 → all three silent, while BEL rang. Same pty, bell works ⇒ bytes arrive, ext just not hooked to that terminal.
|
||||
- **Pattern**: `wenbopan.vscode-terminal-osc-notifier` instruments a terminal only if it exists AFTER ext activation. `terminal.integrated.enablePersistentSessions` (default true) restores terminals at window startup, i.e. BEFORE lazy ext activation → every restored terminal is permanently deaf to OSC. Recurs at each VS Code restart, silently, bell still ringing so it reads as "half broken".
|
||||
- **Fix**: client setting `"terminal.integrated.enablePersistentSessions": false` → no terminal pre-exists activation. Fallback without it: after VS Code start, open a FRESH terminal then `dtach -a ~/.dtach/<session>` (dtach broadcasts, old client can stay or be closed, session never lost).
|
||||
- **Diagnostic shortcut**: bell rings + toast dead on the SAME pty = terminal-instrumentation fault, not audio, not hook, not server. Bell dead + toast alive = audio fault ([[BLK-020]] fault B). The two channels split the search space; check which one survives before anything else.
|
||||
- **Future**: any client-side terminal-parsing ext over Remote-SSH inherits this. Verify instrumentation on the ACTUAL attached pty after every restart, never assume yesterday's terminal.
|
||||
|
||||
## LRN-148 — terminal instrumentation is per-terminal + unpredictable; pre-flight test before attaching
|
||||
- **Refines**: [[LRN-147]] blamed restored-terminals-born-before-activation. Too narrow — counter-example same day: two terminals SAME VS Code window, pts/3 (born 01:58:33) instrumented, pts/7 (born 01:59:29, LATER) deaf. Ext is GLOBAL (marketplace: Enable/Disable pause parsing extension-wide, no per-terminal setting), shells identical on every server-side measurable: `VSCODE_INJECTION=1`, TERM, TERM_PROGRAM, same `--init-file` shell-integration path, ~2-3s between shell start and dtach. Trigger NOT identified.
|
||||
- **Pattern**: treat instrumentation as a per-terminal property that can silently fail for unknown reasons. Cheap pre-flight before committing a long-lived session to a terminal: `printf '\a\a\033]777;notify;NEUF;test\033\\'` typed IN that terminal. Toast → instrumented, attach. Bell only → deaf terminal, open another. Costs 5s, replaces an hour of pty archaeology.
|
||||
- **Recovery**: deaf terminal never repairs. Open fresh terminal, pre-flight it, `dtach -a ~/.dtach/<session>`. dtach broadcasts, so old client may stay attached; session never at risk.
|
||||
- **Diagnostic split (holds)**: bell alive + toast dead = terminal instrumentation. Toast alive + bell dead = client audio ([[BLK-020]]). Neither = bytes never arrive.
|
||||
- **Future**: do NOT assert the born-before-activation cause as established — it fits the first incident, not the second. Unknown trigger is the honest state.
|
||||
|
||||
## LRN-149 — Stop hook payload carries background_tasks; use it to skip premature signals
|
||||
- **Context**: 2026-09-03. User: "notif à la création d'un sous-agent alors qu'il faudrait pas". Instrumented hook, ran probe subagents: NEITHER subagent creation NOR completion calls the hook. Only event = `Stop`, fired when the turn ends right after spawning. Signal was real but LIED ("Finished responding" while work continued).
|
||||
- **Pattern**: dump the real payload (`printf '%s' "$payload" >> file.jsonl`) instead of trusting docs — docs list Stop fields without `background_tasks`, the wire has it: `[{"id","type":"subagent","status":"running","description","agent_type"}]`. Rule: on Stop, `(.background_tasks // []) | length` > 0 → exit 0 silent. Next turn end signals for real. Interaction events (permission/question) always signal, background or not.
|
||||
- **Fail-open**: field absent (older client) → still signal. Missed notification worse than extra one.
|
||||
- **Cross-session gotcha**: hook is user-scope, so EVERY session runs it. A single-file dump (`> file`) gets overwritten by another project's session — append JSONL and filter on `.cwd`. That accident proved `permission_prompt` fires with `message="Claude needs your permission"` (unexercisable in this session under `defaultMode: auto`).
|
||||
- **Future**: any hook needing turn-completion semantics must check background_tasks; "turn ended" ≠ "work done". Verified live: Stop with 0 tasks signals, Stop with 1 running subagent silent.
|
||||
|
||||
@@ -18,13 +18,17 @@ paired same-judge majority, absolute scores triage-only.
|
||||
destructive restore, onboard/onboarder contract, init-project
|
||||
allowed-tools, skills-perso 8/32 detection...).
|
||||
|
||||
- [ ] T4 Phase 1 gate: scorecard checkpoint, user picks optimization set.
|
||||
- [x] T4 Phase 1 gate PASSED: user picked the set — proven by Phase 2
|
||||
running 13/13 units, 0 reverts (DARWIN-2026-08-26.md:23).
|
||||
Ticked by reconcile 2026-09-01.
|
||||
- [x] T5 Phase 2 DONE: 13/13 units, 12 rounds kept 3-0, 0 reverts +
|
||||
bug pass 8 commits kept 3-0 (2 skeptic residuals amended). make test
|
||||
green.
|
||||
- [x] T6 Phase 3 DONE: report .claude/audits/DARWIN-2026-08-26.md + card
|
||||
PNG (playwright fallback). Capitalize pending user approval. Branch
|
||||
UNMERGED — human gate.
|
||||
→ both residuals stale: capitalized a15854a, merged 726464f
|
||||
(reconcile 2026-09-01).
|
||||
|
||||
## 2026-08-25 — user permanent rules: writing + web build + web security (feature/user-writing-web-rules)
|
||||
User supplied 4-block rule text (écris / site / code / vérification); asked:
|
||||
@@ -125,6 +129,8 @@ versioned (durable, referenced by decisions.md e.g. BDR-076). Universal via the
|
||||
655e364 + reconcile e75ea79) — reaches main at next release
|
||||
- [ ] Makefile help text: profile-list help lists 5/10 profiles (:57) —
|
||||
1-line hotfix. (test glob :31 FIXED — has run-*.sh, reconcile 2026-08-25)
|
||||
Re-verified OPEN 2026-09-01: lib/profiles/ has 10, Makefile:57 lists 5
|
||||
(backend, full, seo, web-full, web missing).
|
||||
|
||||
## 2026-07-20 — profile ↔ toggle-external symmetry (feature/profile-managed-externals, BDR-079)
|
||||
Audit verdict: gstack on-demand + design enable already work; DISABLE side
|
||||
|
||||
+64
-10
@@ -6,7 +6,23 @@ Format follows [Keep a Changelog](https://keepachangelog.com/).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [1.5.0] — 2026-09-13
|
||||
|
||||
### Added
|
||||
- **Attention signals on the terminal (BDR-087)** — new
|
||||
`hooks/notify-attention.sh`, wired on `Notification` (input-needed
|
||||
matcher) and on `Stop` (no matcher). Returns a double BEL plus an
|
||||
OSC 777 toast through the `terminalSequence` JSON field, since hooks
|
||||
have no controlling TTY. Signal only: `suppressOutput`, exit 0, zero
|
||||
control-flow effect, which is what separates it from the `decision:
|
||||
"block"` Stop hook [[BDR-083]] refused. Each event reaches the toast
|
||||
as a readable label instead of a snake_case type; events needing no
|
||||
attention (`agent_completed`, `auth_success`) exit silently; a turn
|
||||
that ends with `background_tasks` still running stays quiet and
|
||||
signals at the real end. Client-side prerequisites over Remote-SSH
|
||||
are documented in the script header ([[BLK-020]]): VS Code
|
||||
`accessibility.signals.terminalBell` for the beep, an OSC notifier
|
||||
extension for the Windows toast.
|
||||
- **User permanent rules (BDR-085)** — three new rules/ files from the
|
||||
user's rule text: `writing-style.md` (always-on: em-dash ban, no slop
|
||||
vocabulary, no hedging chains, deliverable self-check),
|
||||
@@ -44,8 +60,23 @@ Format follows [Keep a Changelog](https://keepachangelog.com/).
|
||||
hotfix explicitly runs no floor. Behavioral RED: 16/16 fresh unprimed
|
||||
runs followed the new doctrine (EVAL-027).
|
||||
64 new assertions in `lib/tests/gates.test.sh`.
|
||||
- **`lib/tests/seo-geo-contract.test.sh`** — census locking the seo/geo
|
||||
agent ⇄ dispatcher machine contract: judge verdict grammar, FIX BUNDLE +
|
||||
READY-TO-APPLY sentinel, signals handoff, every STEP header (interiors
|
||||
included), bundle item fields, score labels, scoring blocks, envelope
|
||||
keys (46→71 assertions across the C1 chantier).
|
||||
|
||||
### Changed
|
||||
- **Skill and agent quality campaign, 54 units (BDR-086)** — full darwin
|
||||
v2.1 pass over the 31 personal skill-systems and 23 agents, excluding
|
||||
the gstack/external symlinks and machine-owned units. Fresh baseline
|
||||
mean 83.4; the 13 units under the user-set threshold of 80 were
|
||||
optimized to completion, and verified defects in above-threshold units
|
||||
were fixed in a grouped pass rather than left to ship because the score
|
||||
was good enough. Every round was validated by a paired 3-judge majority
|
||||
reading before and after in one call: 36 unit-round verdicts, 24 batch
|
||||
verdicts, all better, zero reverts. Full report and residual findings:
|
||||
`.claude/audits/DARWIN-2026-08-26.md`.
|
||||
- **seo-analyzer + geo-analyzer de-prescribed for Opus 5 (BDR-082)** —
|
||||
process choreography converted to when-guidance under an
|
||||
audience×mode-range invariant; self-output verification demands removed
|
||||
@@ -56,25 +87,48 @@ Format follows [Keep a Changelog](https://keepachangelog.com/).
|
||||
proven by a controlled before/after `/seo` dogfood — judge replay on
|
||||
frozen signals, 42/42 presence assertions on both runs, blind structural
|
||||
reader: interchangeable, recall improved.
|
||||
|
||||
### Added
|
||||
- **`lib/tests/seo-geo-contract.test.sh`** — census locking the seo/geo
|
||||
agent ⇄ dispatcher machine contract: judge verdict grammar, FIX BUNDLE +
|
||||
READY-TO-APPLY sentinel, signals handoff, every STEP header (interiors
|
||||
included), bundle item fields, score labels, scoring blocks, envelope
|
||||
keys (46→71 assertions across the C1 chantier).
|
||||
- **Global instruction layer recalibrated for the Claude 5 family (BDR-081)** —
|
||||
delegation block is now model-neutral when-guidance (the Opus 4.8
|
||||
under-delegation counter inverted on Opus 5, which over-delegates and gets
|
||||
an injected harness cap); "staff engineer" self-check bar dropped (Opus 5
|
||||
over-verification trigger); finish-whole-task clause added to Deviations;
|
||||
written-deliverable length rule added. 308/320 lines.
|
||||
- **Default session model is now `opus[1m]`** (was `claude-fable-5[1m]`).
|
||||
- **`skills-external/emil-design-eng/` untracked** — the file is curl'd
|
||||
from upstream by `install-plugins.sh` when absent and re-fetched by
|
||||
every `update-all.sh` run, so tracking it produced a repo diff on each
|
||||
upstream edit. Same category as `frontend-design/` and `impeccable/`,
|
||||
already ignored on that rationale; a fresh clone re-fetches it.
|
||||
`design-motion-principles/` has the same overwrite behaviour but no
|
||||
bootstrap clone yet, so it stays tracked until that gap closes.
|
||||
|
||||
### Fixed
|
||||
- **hotfix wiped tolerated in-progress edits on its revert path** — every
|
||||
failure branch ran `git restore .`, destroying user edits the run had
|
||||
tolerated. Now a `git stash create` pre-flight snapshot plus a
|
||||
file-scoped restore, and the security gate is fresh-dispatch only.
|
||||
- **skills-perso listed 8 of 31 personal skills** — detection rebuilt on
|
||||
the `link.sh` symlink convention (symlink = external, real dir =
|
||||
personal, gitignored = machine-generated). Live result 31/31, no false
|
||||
positives.
|
||||
- **plan-challenger** — `ERROR` joined the load-bearing verdict grammar
|
||||
(STEP 1 emitted it, the parser enum omitted it); grounded-but-uncertain
|
||||
findings now file as `[MINOR]` with the uncertainty stated, instead of
|
||||
being self-censored (Opus 5 follows conservative-reporting clauses
|
||||
literally).
|
||||
- **design-toolchain hook** — dropped `\bux\b` (2 French-prose false
|
||||
positives; 3rd tightening pass, series LRN-1005/1007); `\bui\b` kept and
|
||||
locked by a must-fire test row.
|
||||
- **plan-challenger** — grounded-but-uncertain findings now file as `[MINOR]`
|
||||
with the uncertainty stated, instead of being self-censored (Opus 5 follows
|
||||
conservative-reporting clauses literally).
|
||||
- **Agent and skill defects found by the campaign's judges** —
|
||||
`init-project` allowed-tools lacked `Agent` and `Skill` while every step
|
||||
dispatches; `commit-change` conflict grep now covers all 7 unmerged
|
||||
codes; `tour --report-only` no longer commits; `harden` severity defers
|
||||
to the calibrated guide and the late SSL Labs grade has an assigned
|
||||
actor; handover writers' stale chapter refs corrected and the anchor
|
||||
gate ordered; `security-auditor` documents the hotfix no-verifier
|
||||
carve-out; `close` enumerates STEP 5C and passes `--no-push` through;
|
||||
`prune-memory` drops a false "v1-untested" note; `code-clean` attributes
|
||||
its executor correctly; plugin-check and onboard fixtures de-drifted.
|
||||
|
||||
## [1.4.0] — 2026-07-22
|
||||
|
||||
|
||||
@@ -1,24 +1,67 @@
|
||||
#!/usr/bin/env bash
|
||||
# Notification hook — signal the user through the terminal when Claude
|
||||
# needs input (permission prompt, question, idle wait).
|
||||
# Notification + Stop hook — signal the user through the terminal when
|
||||
# Claude needs input (permission, question, idle wait) or has finished
|
||||
# responding. Each case gets its own readable label so the toast says
|
||||
# which one fired.
|
||||
#
|
||||
# Runs on the remote (Linux); the only channel that crosses SSH into the
|
||||
# VS Code client is the terminal stream. Hooks have no controlling TTY,
|
||||
# so the sequence goes through the supported `terminalSequence` JSON
|
||||
# output field and Claude Code writes it to the terminal:
|
||||
# - BEL x2 (double beep) -> sound, needs VS Code setting
|
||||
# accessibility.signals.terminalBell { "sound": "on" }
|
||||
# accessibility.signals.terminalBell { "sound": "on" } AND a non-zero
|
||||
# volume for Code in the Windows volume mixer (BLK-020).
|
||||
# - OSC 777 notify -> Windows toast via the client-side extension
|
||||
# "Terminal Notification" (wenbopan.vscode-terminal-osc-notifier)
|
||||
# "Terminal Notification" (wenbopan.vscode-terminal-osc-notifier).
|
||||
# A terminal can be deaf to OSC while the bell still rings; test it
|
||||
# before attaching a session to it (LRN-148).
|
||||
# Both are invisible no-ops in terminals that ignore them.
|
||||
set -u
|
||||
|
||||
msg=$(jq -r '.message // .notification_type // empty' 2>/dev/null \
|
||||
| tr -d '\000-\037' | cut -c1-200)
|
||||
[ -n "$msg" ] || msg="Claude Code needs your input"
|
||||
payload=$(cat 2>/dev/null)
|
||||
read_field() {
|
||||
printf '%s' "$payload" | jq -r "$1 // empty" 2>/dev/null \
|
||||
| tr -d '\000-\037' | cut -c1-160
|
||||
}
|
||||
|
||||
# How many background tasks are still running as the hook fires.
|
||||
background_count() {
|
||||
count=$(printf '%s' "$payload" | jq -r '(.background_tasks // []) | length' 2>/dev/null)
|
||||
case "$count" in ''|*[!0-9]*) echo 0 ;; *) echo "$count" ;; esac
|
||||
}
|
||||
|
||||
event=$(read_field '.notification_type')
|
||||
[ -n "$event" ] || event=$(read_field '.hook_event_name')
|
||||
|
||||
|
||||
|
||||
case "$event" in
|
||||
# Turn end while a subagent still runs is not the real end: stay silent,
|
||||
# the next turn end will signal once the work is actually done.
|
||||
Stop) [ "$(background_count)" -eq 0 ] || exit 0
|
||||
label="Finished responding" ;;
|
||||
permission_prompt) label="Needs your permission" ;;
|
||||
agent_needs_input) label="Asks you a question" ;;
|
||||
idle_prompt) label="Waiting for you" ;;
|
||||
elicitation_dialog|elicitation_url_dialog) label="Needs your input" ;;
|
||||
# anything else (agent_completed, auth_success, quota_*) stays silent:
|
||||
# signal only for turn end and moments needing the user.
|
||||
*) exit 0 ;;
|
||||
esac
|
||||
|
||||
detail=$(read_field '.message')
|
||||
if [ -n "$detail" ]; then
|
||||
# Claude Code's own wording often restates the label ("Claude needs your
|
||||
# permission"). Append it only when it actually adds something.
|
||||
short=$(printf '%s' "$detail" | tr '[:upper:]' '[:lower:]' | sed 's/^claude //')
|
||||
case "$(printf '%s' "$label" | tr '[:upper:]' '[:lower:]')" in
|
||||
*"$short"*) : ;;
|
||||
*) label="${label}: ${detail}" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
bell=$(printf '\a')
|
||||
esc=$(printf '\033')
|
||||
seq="${bell}${bell}${esc}]777;notify;Claude Code;${msg}${esc}\\"
|
||||
seq="${bell}${bell}${esc}]777;notify;Claude Code;${label}${esc}\\"
|
||||
jq -cn --arg seq "$seq" '{suppressOutput: true, terminalSequence: $seq}'
|
||||
exit 0
|
||||
|
||||
@@ -286,6 +286,18 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"Stop": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "bash ~/.claude/hooks/notify-attention.sh",
|
||||
"timeout": 5,
|
||||
"statusMessage": "Ringing terminal bell..."
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"UserPromptSubmit": [
|
||||
{
|
||||
"hooks": [
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
1.4.0
|
||||
1.5.0
|
||||
|
||||
Reference in New Issue
Block a user