From 3d3e3cd918f4622c680ff310ddf25b33c2f98690 Mon Sep 17 00:00:00 2001 From: _david Date: Sun, 6 Sep 2026 05:27:10 +0700 Subject: [PATCH] chore(agent-hub): sync hub-tokens fixes, batch verify, AppendOnly, isolation proof, persona-load - boot/SKILL.md: fix /boot reading dev-loop-archive.md every session (was reading ALL files in haven/diagrams/, now excludes archive) - pick_next.md: same archive-exclusion clarification; append new node rows at the END of the PM status table only (AppendOnly) - implementer + verifier manifest.yaml: add AppendOnly hard rule - agent-hub/.gitattributes: haven/diagrams/*.prime-mermaid.md merge=union, reduces conflicts when multiple branches add nodes concurrently - verify_seal.md: batch verify (all-pending / multiple note paths, spawn cost paid once per batch, verdict still independent per node); isolation proof (## Isolation proof line proving a genuinely separate subagent spawn, citeable audit trail for NeverVerifyOwnWork) - worker/SKILL.md: document both of the above for /worker verifier - evidence/README.md: document the new ## Isolation proof field - .claude/skills/persona-load/: new skill, load an expert persona/panel on demand from this project's own persona library (once built) Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01PmrS7woH6DGJ5oz7CjhXhr --- .claude/skills/boot/SKILL.md | 7 +- .claude/skills/persona-load/SKILL.md | 80 +++++++++++++++++++ .claude/skills/worker/SKILL.md | 15 +++- agent-hub/.gitattributes | 1 + agent-hub/evidence/README.md | 6 ++ .../haven/workers/implementer/manifest.yaml | 4 + .../workers/implementer/recipes/pick_next.md | 7 +- .../haven/workers/verifier/manifest.yaml | 3 + .../workers/verifier/recipes/verify_seal.md | 61 +++++++++++--- 9 files changed, 171 insertions(+), 13 deletions(-) create mode 100644 .claude/skills/persona-load/SKILL.md create mode 100644 agent-hub/.gitattributes diff --git a/.claude/skills/boot/SKILL.md b/.claude/skills/boot/SKILL.md index 117f232..c164457 100644 --- a/.claude/skills/boot/SKILL.md +++ b/.claude/skills/boot/SKILL.md @@ -18,7 +18,12 @@ description: Đọc doctrine + diagram + evidence gần nhất của agent-hub, đó không xuất hiện trong phiên này. 3. Đọc `agent-hub/doctrine/MEMORY.md` — lấy path, stack, lệnh chính xác. 4. Đọc `agent-hub/doctrine/domains/PROJECT.md` — invariants/traps/decisions. -5. Đọc mọi file trong `agent-hub/haven/diagrams/` — đếm node theo PM status. +5. Đọc mọi file trong `agent-hub/haven/diagrams/` **TRỪ** file có chữ + `archive` trong tên (`dev-loop-archive.md`...) — [sửa 2026-09-05] đó là + cold storage theo thiết kế (xem ghi chú token-discipline trong + `dev-loop.prime-mermaid.md` + `hub-tokens.md`), đọc lại mỗi phiên phá + vỡ đúng mục đích archive. Chỉ đếm node + PM status từ file KHÔNG phải + archive. 6. Đọc `agent-hub/haven/workers/*/manifest.yaml` — roster worker khả dụng. 7. Đọc tối đa 5 evidence note gần nhất trong `agent-hub/evidence/` (implementer + verifier, mới nhất trước). Để liệt kê, dùng diff --git a/.claude/skills/persona-load/SKILL.md b/.claude/skills/persona-load/SKILL.md new file mode 100644 index 0000000..4f2603d --- /dev/null +++ b/.claude/skills/persona-load/SKILL.md @@ -0,0 +1,80 @@ +--- +name: persona-load +description: "Load an on-demand expert-persona or a named panel from this project's own persona library (outside agent-hub/), printing the loader's SEALED output for the current worker session to read. Advisory only, read-only, no side effects." +argument-hint: "/ | -p | -l [category]" +--- + +# /persona-load — load an expert persona or panel on demand + +Read-only. Wraps this project's own `scripts/load_persona.sh` (lives in +the code repo, NOT in `agent-hub/` — a persona loader is code, and +`CODE_IN_HAVEN` forbids code inside `haven/`). Prints one persona or a +whole panel so the current implementer/verifier pass can borrow that +expert's judgment on a domain-specific question — advisory only, never a +substitute for real evidence. + +## Why this exists +A persona is a high-precision pointer into the model's latent space: +naming a real expert activates a cluster of domain knowledge that would +otherwise take paragraphs to restate. Loading ALL personas up front gives +zero lift and wastes tokens (empirically, per the persona-system brief +this skill implements) — this command is the on-demand hook so a worker +only pays for the 1 persona (or panel of 2-4) actually relevant to the +task at hand. + +## Steps +1. **Locate the loader.** Check `scripts/load_persona.sh` exists at the + project root (or whatever `<>` this project declared in + `doctrine/domains/PROJECT.md`, if it did). If it doesn't exist, stop + and report: "persona system not set up in this project — build it + first via `/worker implementer` using the persona-system brief, then + retry" — never fabricate a persona inline as a fallback. +2. **Parse `$ARGUMENTS`**: + - `/` → load that one persona file. + - `-p ` → load every member of that named panel (2-4 files). + - `-l [category]` → list available personas (all, or filtered to one + category) instead of loading content — for browsing. + - No/invalid arguments → run `scripts/load_persona.sh -h` and print + its usage output verbatim, don't invent your own usage text. +3. **Run the loader for real** (`scripts/load_persona.sh `), READ + BACK its stdout verbatim — this includes the `=== SEAL ===` header + + sha256 the script itself prints. Never paraphrase a persona's content + into your own summary; print what the script actually returned. +4. **Use the result as a lens, not a ruling.** Whatever the loaded + persona/panel says informs the current implementer's or verifier's + judgment on a domain-specific question. It NEVER overrides a hard rule + (`TestsBeforeDone`, `EvidencePerAction`, `NeverVerifyOwnWork`, the 5 + forbidden states, this project's own `doctrine/`) and never counts as + evidence by itself — a verifier still needs a real cited test/output + to SEAL; "persona X approved this" is not an acceptance criterion. + +## Hard rules honored +- `PersonaAsLensNotAuthority` — a persona/panel informs judgment, never + grants capability, never overrides `doctrine/`/the 5 forbidden + states/a safety file, never substitutes for real evidence. Layering: + `<> > agent-hub doctrine > repo conventions > + persona`. +- `CodeStaysOutOfHaven` — the loader script and persona library live in + the project's own code tree, never inside `agent-hub/haven/` or + `agent-hub/doctrine/` (would trip `CODE_IN_HAVEN`, and would silently + inflate the recurring per-session token cost `/hub-tokens` tracks). +- `ReadBackBeforeClaim` — always print the loader's real stdout, never a + paraphrase of what a persona file "probably says". + +## Failure branches +| Failure | Handling | +|---|---| +| `scripts/load_persona.sh` missing | Report "not set up yet", point at building it via `/worker implementer`, stop — don't invent persona content inline | +| Requested `/` or panel not found | Let the loader's own "fail loudly with a suggestion" behavior surface — print its real stderr, don't guess a substitute persona | +| Loader script errors out (bad permissions, syntax) | Report the real error verbatim, don't retry with `sudo`/`chmod` or work around it silently | + +## Runtime +`/persona-load /` — load one persona. +`/persona-load -p ` — load a whole panel. +`/persona-load -l [category]` — list available personas. +Requires the project to already have its persona system built (loader + +library in its own code tree — see `doctrine/domains/PROJECT.md` for this +project's `<>`/safety-file names if declared there). Building that +system the first time is a normal code change — run it through +`/worker implementer "build the on-demand expert-persona system"` like +any other task, not through this command. diff --git a/.claude/skills/worker/SKILL.md b/.claude/skills/worker/SKILL.md index a3223fb..9afdc8c 100644 --- a/.claude/skills/worker/SKILL.md +++ b/.claude/skills/worker/SKILL.md @@ -9,6 +9,13 @@ argument-hint: "" > Chạy MỘT worker cho MỘT task. Không bao giờ làm việc "chung chung" ngoài > vai trò — mọi hành động phải trace về `haven/workers//`. +> [thêm 2026-09-05] Riêng `verifier`, tham số task có thể là 1 đường dẫn +> evidence note, NHIỀU đường dẫn cùng lúc (batch), hoặc từ khoá +> `all-pending` (mọi node đang `sealed_pending_verifier` trên diagram +> active) — xem "Batch verify" trong `recipes/verify_seal.md`. Batch chỉ +> gộp chi phí spawn subagent (load bundle 1 lần cho cả lô), verdict vẫn +> tính RIÊNG, ĐỘC LẬP cho từng node. + ## Vòng chạy bắt buộc 1. **Load bundle** — đọc đúng thứ tự: `agent-hub/haven/workers//manifest.yaml` → @@ -26,7 +33,13 @@ argument-hint: "" chấm, và node liên quan trên diagram. Subagent tự đọc note + diagram + `CLAUDE.md`, tự viết verdict vào `evidence/verifier/`, tự cập nhật PM status nếu SEAL. Đây chính là cách hiện thực `NeverVerifyOwnWork` thật - — subagent không có lịch sử hội thoại của lượt implement. + — subagent không có lịch sử hội thoại của lượt implement. [thêm + 2026-09-06] Không có hook nào chặn thật việc bỏ qua bước spawn này — + `NeverVerifyOwnWork` là ràng buộc hạ tầng, không phải lời hứa tự + giác. Phòng vệ thật là dấu vết citeable: `recipes/verify_seal.md` + bước 1b bắt verifier ghi bằng chứng spawn riêng vào dòng + `## Isolation proof` của verdict note, để 1 audit sau này phát hiện + được nếu bước tách context bị bỏ qua. 3. **Follow recipe** — chọn recipe khớp `quick_actions` của worker: - `implementer`: `pick_next` rồi `implement` (xem `recipes/pick_next.md`, `recipes/implement.md`). diff --git a/agent-hub/.gitattributes b/agent-hub/.gitattributes new file mode 100644 index 0000000..e141f51 --- /dev/null +++ b/agent-hub/.gitattributes @@ -0,0 +1 @@ +haven/diagrams/*.prime-mermaid.md merge=union diff --git a/agent-hub/evidence/README.md b/agent-hub/evidence/README.md index be48788..663e275 100644 --- a/agent-hub/evidence/README.md +++ b/agent-hub/evidence/README.md @@ -29,6 +29,12 @@ Date as `YYYY-mm-dd`, slug kebab-case from the task name. ## Format — verifier verdict - Worker (subagent, dispatched via Agent tool) · Node · New PM status (PENDING/SEALED/REOPEN) +- `## Isolation proof` — [added 2026-09-06, fed back from real production + use in `datvt243.github.io`] cites whatever makes this a genuinely + separate subagent spawn (see `recipes/verify_seal.md` step 1b) — not + technically enforced by a hook, but a missing/suspicious line here is + itself citeable evidence for a later audit that `NeverVerifyOwnWork`'s + subagent-isolation step was skipped. - `## Reasoning` — cite evidence for each criterion - `## Missing` — only present on REOPEN - `## Re-run` — [added 2026-09-02] `none`/`partial`/`full`, declared diff --git a/agent-hub/haven/workers/implementer/manifest.yaml b/agent-hub/haven/workers/implementer/manifest.yaml index ba7cd28..c155460 100644 --- a/agent-hub/haven/workers/implementer/manifest.yaml +++ b/agent-hub/haven/workers/implementer/manifest.yaml @@ -13,5 +13,9 @@ hard_rules: - SmallestDiff # prefer the smallest diff, no extra rename/refactor - TestsBeforeDone # must run real tests before reporting done - NodeBeforeCode # must have a diagram node before writing code + - AppendOnly # [added 2026-09-05] new node rows always appended at + # the end of the PM status table, never inserted mid- + # table — required for agent-hub/.gitattributes' + # merge=union to merge cleanly across branches reads: [NORTHSTAR.md, doctrine/MEMORY.md, doctrine/domains/, haven/diagrams/] writes: [evidence/implementer/] diff --git a/agent-hub/haven/workers/implementer/recipes/pick_next.md b/agent-hub/haven/workers/implementer/recipes/pick_next.md index e1917d8..b839ec2 100644 --- a/agent-hub/haven/workers/implementer/recipes/pick_next.md +++ b/agent-hub/haven/workers/implementer/recipes/pick_next.md @@ -18,6 +18,9 @@ — reuse from `/boot` if available (see GUARD above), else `Read` fresh. 2. Get every diagram in `haven/diagrams/`, list every node + PM status — reuse from `/boot` if available (see GUARD above), else `Read` fresh. + [clarified 2026-09-05] "every diagram" means every file WITHOUT + `archive` in its name — an archive file is cold storage, not re-read + here, matching `/boot` step 5's rule exactly. 3. Find the earliest PENDING node on the critical path (e.g. the seed node `fix-chrome-executable-path` in `dev-loop.prime-mermaid.md`). 4. No match → don't invent work; report "no PENDING node" clearly, stop. @@ -36,12 +39,12 @@ the line `## Hub bytes before: ` from step 7. ## Hard rules honored -`NodeBeforeCode` | `EvidencePerAction` | `NoSilentFailure` +`NodeBeforeCode` | `EvidencePerAction` | `NoSilentFailure` | `AppendOnly` ## Failure branches | Failure | Handling | |---|---| -| No diagram exists yet | Create `haven/diagrams/.prime-mermaid.md` matching the `dev-loop` format | +| No diagram exists yet | Create `haven/diagrams/.prime-mermaid.md` matching the `dev-loop` format. [added 2026-09-05] Always APPEND the new row at the END of the PM status table, never insert it in the middle — required for `agent-hub/.gitattributes`' `merge=union` to merge cleanly when 2 branches each add a different new node around the same time. | | Task is ambiguous | Stop and ask, don't guess | ## Runtime diff --git a/agent-hub/haven/workers/verifier/manifest.yaml b/agent-hub/haven/workers/verifier/manifest.yaml index 996f633..6483f89 100644 --- a/agent-hub/haven/workers/verifier/manifest.yaml +++ b/agent-hub/haven/workers/verifier/manifest.yaml @@ -12,6 +12,9 @@ hard_rules: - EvidenceOnly # never trust inference over real evidence - NeverVerifyOwnWork # never grade a diff you wrote yourself - RatchetOnly # PM status only moves forward, never backward + - AppendOnly # [added 2026-09-05] update a node's own row IN PLACE + # on SEAL — never reorder/move rows in the PM status + # table, same reason as the implementer's AppendOnly reads: [evidence/implementer/, haven/diagrams/, doctrine/MEMORY.md, CLAUDE.md] # doctrine/MEMORY.md: recipe step 4 needs it to check the note's command. # No NORTHSTAR.md — recipe never uses it, was dead weight on every spawn. diff --git a/agent-hub/haven/workers/verifier/recipes/verify_seal.md b/agent-hub/haven/workers/verifier/recipes/verify_seal.md index 81c5a65..57f4509 100644 --- a/agent-hub/haven/workers/verifier/recipes/verify_seal.md +++ b/agent-hub/haven/workers/verifier/recipes/verify_seal.md @@ -1,14 +1,38 @@ > the gate. # Contract -- Input: path to an evidence note under `evidence/implementer/`. -- Output: `{verdict: SEAL|REOPEN, node, cited: string[], missing: string[], - forbidden_hit: string|null, pm_updated: boolean}` +- Input: path to an evidence note under `evidence/implementer/`, OR + multiple paths (batch), OR `all-pending` (every node currently + `sealed_pending_verifier` on the active diagram — see "Batch verify" + below). [batch added 2026-09-05] +- Output: AN ARRAY, 1 element per node: `{verdict: SEAL|REOPEN, node, + cited: string[], missing: string[], forbidden_hit: string|null, + pm_updated: boolean, rerun: none|partial|full, isolation_proof: + string}` — `isolation_proof` is a real self-declaration (step 1b), not + inferred from outside. - REFUSAL: if this exact session wrote the diff under review → refuse immediately: "I wrote this, a separate verifier pass is required." (`NeverVerifyOwnWork`) — in practice moot, since verify_seal runs as a fresh subagent dispatched via the Agent tool with no implementation - history. + history. In a batch, this check still applies PER NODE: refuse just a + self-written node, don't cancel the rest of the batch. + +## Batch verify [added 2026-09-05] +The heaviest cost of a verify pass isn't the act of verifying — it's +reloading the whole bundle + doctrine on every subagent spawn. Batch +verify pays that cost EXACTLY ONCE for N nodes instead of N times, +without changing anything about the substance of verifying: +- The fresh-subagent-context guarantee + self-refusal check (step 1) + apply ONCE for the whole batch. +- Steps 2-13 (read note, check criteria, scan forbidden states, verdict, + write verdict, Re-run declaration) run REPEATEDLY, INDEPENDENTLY, for + EACH node — using node A's evidence/reasoning to infer node B's verdict + is forbidden, even if the two notes look similar. Each node still gets + its own evidence, own verdict, own verdict note. +- Being in a batch is NEVER an excuse to loosen any criterion in steps + 2-13 — batching only folds the SPAWN COST, never the VERDICT. +- `all-pending`: first list every `sealed_pending_verifier` node on + `dev-loop.prime-mermaid.md`, then run the full procedure below on each. ## Re-run scope [cost-driven, added 2026-09-02] Default: AUDIT the note, don't independently re-run `npm test`/`npm run @@ -38,8 +62,16 @@ asks for — this section pins the boundary. ## Steps 1. REFUSE SELF-GRADING FIRST — did I write this diff in this session? (No, by construction — subagent has a fresh context.) -2. Read the NOTE — only the note, do NOT open the diff directly. - (`EvidenceOnly`) +1b. [added 2026-09-06, fed back from real production use in + `datvt243.github.io`] Record proof this pass is really a separate + subagent context, not a self-report: cite whatever this invocation was + actually spawned with that the implementer pass didn't have (e.g. the + `description`/task string passed to the Agent tool for this spawn) — + write it into the note's `## Isolation proof` line (step 12a). No hook + technically blocks a skipped isolation — this only leaves a citeable + trail for a later audit. +2. [LOOP STARTS HERE FOR EACH NODE if batch] Read the NOTE — only the + note, do NOT open the diff directly. (`EvidenceOnly`) 3. Read the NODE — pull acceptance criteria from `haven/diagrams/`, forbidden states from `CLAUDE.md`. [GUARD, added 2026-08-31] Don't `Read agent-hub/CLAUDE.md` yourself for this — same mechanism as @@ -61,8 +93,14 @@ asks for — this section pins the boundary. 10. Verdict is exactly one of: SEAL (every criterion has cited evidence) or REOPEN (one important gap is enough). 11. Only on SEAL: update the ratchet/PM status on - `haven/diagrams/dev-loop.prime-mermaid.md`. + `haven/diagrams/dev-loop.prime-mermaid.md`. [added 2026-09-05] Update + the node's own row IN PLACE (state column → SEALED) — never reorder, + move, or re-sort rows in the table (`AppendOnly`); this keeps + `agent-hub/.gitattributes`' `merge=union` able to merge cleanly + across branches. 12. Write the verdict to `evidence/verifier//-{seal|reopen}.md`. +12a. [added 2026-09-06] In that note, include the `## Isolation proof` + line from step 1b. 12b. [added 2026-09-02] In the verdict note, truthfully declare 1 line `## Re-run`: `none` (audit-only, the correct default per "Re-run scope" above), `partial` (name exactly which command was re-run), or @@ -84,7 +122,8 @@ asks for — this section pins the boundary. rest of `evidence/`. ## Hard rules honored -`NeverVerifyOwnWork` | `EvidenceOnly` | `VerdictOnly` | `RatchetOnly` +`NeverVerifyOwnWork` | `EvidenceOnly` | `VerdictOnly` | `RatchetOnly` | +`AppendOnly` ## Failure branches | Failure | Handling | @@ -96,4 +135,8 @@ asks for — this section pins the boundary. ## Runtime Dispatched as a subagent (Agent tool) by `/worker verifier ""` or by `/todo` round 2 — never run in the implementer's own -session. +session. [added 2026-09-05] `/worker verifier " ..."` +(multiple evidence note paths) or `/worker verifier all-pending` spawns +ONE subagent that verifies every queued node independently — use this +after several small implementer passes have piled up, instead of one +`/worker verifier` call per node.