From 03b7238f6869564ba1a27bcdcc525f98c087ba1e Mon Sep 17 00:00:00 2001 From: "lei.chen" Date: Fri, 30 Oct 2026 05:52:23 +0000 Subject: [PATCH] chore(wolf): restore OPENWOLF.md protocol + fresh anatomy/memory session state The Aug 30 scheduler-framework merge (3b6f53bb) dropped .wolf/OPENWOLF.md, anatomy.md and memory.md (Rongsong's tree carries no .wolf state); CLAUDE.md @-includes OPENWOLF.md, so the session protocol has been silently missing since. Restore the protocol verbatim (ba4e5fd2) and commit the current hardening-plan/Phase 0/1/HA-analysis bookkeeping. Co-Authored-By: Claude Code --- .wolf/OPENWOLF.md | 139 ++++++++++++++++++++++++++++++++++++++++++++++ .wolf/anatomy.md | 8 +++ .wolf/memory.md | 7 +++ 3 files changed, 154 insertions(+) create mode 100644 .wolf/OPENWOLF.md create mode 100644 .wolf/anatomy.md create mode 100644 .wolf/memory.md diff --git a/.wolf/OPENWOLF.md b/.wolf/OPENWOLF.md new file mode 100644 index 00000000..3688ad22 --- /dev/null +++ b/.wolf/OPENWOLF.md @@ -0,0 +1,139 @@ +# OpenWolf Operating Protocol + +You are working in an OpenWolf-managed project. These rules apply every turn. + +## File Navigation + +1. Check `.wolf/anatomy.md` BEFORE reading any file. It has a 2-3 line description and token estimate for every file in the project. +2. If the description in anatomy.md is sufficient for your task, do NOT read the full file. +3. If a file is not in anatomy.md, search with Grep/Glob, then update anatomy.md with the new entry. + +## Code Generation + +1. Before generating code, read `.wolf/cerebrum.md` and respect every entry. +2. Check the `## Do-Not-Repeat` section — these are past mistakes that must not recur. +3. Follow all conventions in `## Key Learnings` and `## User Preferences`. + +## After Actions + +1. After every significant action, append a one-line entry to `.wolf/memory.md`: + `| HH:MM | description | file(s) | outcome | ~tokens |` +2. After creating, deleting, or renaming files: update `.wolf/anatomy.md`. + +## Cerebrum Learning (MANDATORY — every session) + +OpenWolf's value comes from learning across sessions. You MUST update `.wolf/cerebrum.md` whenever you learn something useful. This is not optional. + +**Update `## User Preferences` when the user:** +- Corrects your approach ("no, do it this way instead") +- Expresses a style preference (naming, structure, formatting) +- Shows a preferred workflow or tool choice +- Rejects a suggestion — record what they preferred instead +- Asks for more/less detail, verbosity, explanation + +**Update `## Key Learnings` when you discover:** +- A project convention not obvious from the code (e.g., "tests go in __tests__/ not test/") +- A framework-specific pattern this project uses +- An API behavior that surprised you +- A dependency quirk or version constraint +- How modules connect or data flows through the system + +**Update `## Do-Not-Repeat` (with date) when:** +- The user corrects a mistake you made +- You try something that fails and find the right approach +- You discover a gotcha that would trip up a fresh session + +**Update `## Decision Log` when:** +- A significant architectural or technical choice is made +- The user explains why they chose approach A over B +- A trade-off is explicitly discussed + +**The bar is LOW.** If in doubt, add it. A cerebrum entry that's slightly redundant costs nothing. A missing entry means the next session repeats the same discovery process. + +## Bug Logging (MANDATORY) + +**Log a bug to `.wolf/buglog.json` whenever ANY of these happen:** +- The user reports an error, bug, or problem +- A test fails or a command produces an error +- You fix something that was broken +- You edit a file more than twice to get it right +- An import, module, or dependency is missing or wrong +- A runtime error, type error, or syntax error occurs +- A build or lint command fails +- A feature doesn't work as expected +- You change error handling, try/catch blocks, or validation logic +- The user says something "doesn't work", "is broken", or "shows wrong X" + +**Before fixing:** Read `.wolf/buglog.json` first — the fix may already be known. + +**Before appending a new entry:** search existing bugs for the same `file` + overlapping `root_cause`/`error_message`. If a match exists, update THAT entry (`occurrences += 1`, `last_seen = now`, append context to `fix` if the resolution differs) instead of creating a new `bug-NNN`. Never create a second entry under an id that already exists — assign the next unused number after the current max `bug-NNN` in the file (never restart from `bug-001`; a restarted counter collides with existing history and is unrecoverable without a git-history merge). If you fixed something genuinely new, append with this structure: +```json +{ + "id": "bug-NNN", + "timestamp": "ISO date", + "error_message": "exact error or user complaint", + "file": "file that was fixed", + "root_cause": "why it broke", + "fix": "what you changed to fix it", + "tags": ["relevant", "keywords"], + "related_bugs": [], + "occurrences": 1, + "last_seen": "ISO date" +} +``` +Always preserve the top-level `{"version": 1, "bugs": [...]}` wrapper — never write a bare array. + +**The threshold is LOW.** When in doubt, log it. A false positive in the bug log costs nothing. A missed bug means repeating the same mistake later. + +**Integrity is automated, not optional:** a Stop hook (`.wolf/hooks/stop.js`) validates `.wolf/buglog.json` (JSON validity, wrapper format, duplicate IDs, ID count/max going backwards vs. the last commit) after every turn and, if it's valid and grew, commits it standalone (`chore(wolf): checkpoint buglog.json (N bugs)`) so git history is always a recoverable backup. If it shrank or fails validation, the hook refuses to commit and prints why — treat that warning as a stop-and-investigate signal, not noise to scroll past. + +## Token Discipline + +- Never re-read a file already read this session unless it was modified since. +- Prefer anatomy.md descriptions over full file reads when possible. +- Prefer targeted Grep over full file reads when searching for specific code. +- If appending to a file, do not read the entire file first. + +## Design QC + +When the user asks you to check, evaluate, or improve the design/UI of their app: + +1. Run `openwolf designqc` via Bash to capture screenshots. + - The command auto-detects a running dev server, or starts one from package.json if needed + - Use `--url ` only if auto-detection fails + - The command saves compressed JPEG screenshots to `.wolf/designqc-captures/` + - Full pages are captured as sectioned viewport-height images (top, section2, ..., bottom) +2. Read the captured screenshot images from `.wolf/designqc-captures/` using the Read tool. +3. Evaluate the design against modern standards (Shadcn UI, Tailwind, clean React patterns): + - Spacing and whitespace consistency + - Typography hierarchy and readability + - Color contrast and accessibility (WCAG) + - Visual hierarchy and focal points + - Component consistency + - Whether the design looks "dull" or "white-coded" (generic, no personality) +4. Provide specific, actionable feedback with fix suggestions. +5. If the user approves, implement the fixes directly in their code. +6. After fixes, re-run `openwolf designqc` to capture new screenshots and verify improvement. + +**Token awareness:** Each screenshot costs ~2500 tokens. The command compresses images (JPEG quality 70, max width 1200px) to minimize cost. For large apps, use `--routes / /specific-page` to limit captures. + +## Reframe — UI Framework Selection + +When the user asks to change, pick, migrate, or "reframe" their project's UI framework: + +1. Read `.wolf/reframe-frameworks.md` for the full framework knowledge base. +2. Ask the user the decision questions from the file (current stack, priority, Tailwind usage, theme preference, app type). Stop early once the choice narrows to 1-2 options. +3. Present a recommendation with reasoning based on the comparison matrix. +4. Once the user confirms, use the selected framework's prompt from the file — **adapted to the actual project** using `.wolf/anatomy.md` for real file paths, routes, and components. +5. Execute the migration: install dependencies, update config, refactor components. +6. After migration, run `openwolf designqc` to verify the new look. + +**Do NOT read the entire reframe-frameworks.md into context upfront.** Read the decision questions and comparison matrix first (~50 lines). Only read the specific framework's prompt section after the user chooses. + +## Session End + +Before ending or when asked to wrap up: + +1. Write a session summary to `.wolf/memory.md`. +2. Review the session: did you learn anything? Did the user correct you? Did you fix a bug? If yes, update `.wolf/cerebrum.md` and/or `.wolf/buglog.json`. +3. Do NOT manually `git add`/commit `.wolf/buglog.json` yourself as part of a feature/task commit — the Stop hook checkpoints it standalone once it validates cleanly (see Bug Logging above). Mixing it into a feature commit just duplicates that history under an unrelated message. diff --git a/.wolf/anatomy.md b/.wolf/anatomy.md new file mode 100644 index 00000000..6ae70248 --- /dev/null +++ b/.wolf/anatomy.md @@ -0,0 +1,8 @@ +# Anatomy + +Repo map notes for session context. + +- `scheduler-hardening-plan.md` (repo root, 2026-10-29) — phased scheduler hardening plan (rejoin path & state management). Phase 0: structural regression tests (RECONCILING 3-path resInUse symmetry, rejoin trigger contract, reset+charge symmetry). Phase 1: bug-1521 reason-ownership threading contract locked by structural scan test (modeled on test_picker_pendreason_factory_audit.c). Phase 2 (core): redefine rejoin as atomic discard of derived state + full rebuild from controller push (mirrors snapshot_load.c load order), new `core_rebuild.c`, REBUILD_PENDING window; incremental merge semantics retained for healthy sessions. Phase 3: replay-level rejoin boundary recording + state/decision equivalence verification via recording.c/sim_verify.c. Phase 4: edge items (bug-1854 live resource-apply via rebuild entry, bug-1841 regression coverage, commit-watermark withheld-job redelivery test). +- `src/scheduler/testsuite/test_res_account_symmetry.c` (b20caf8d, 2026-10-30) — Phase 0 test 1: three-path UNAVAIL/RECONCILING skip symmetry lock (core_reset_workers / sched_update_account / sched_reconcile_host_resource_usage driven in one core per round via real sched_account_jobs; zero-drift across rounds; bug-1799 live shape = +1 charge/round caught by mutation injection). Link: foreach-minus-TU-list pattern (like sched_trace_error_paths_test) — test #includes core.c/core_session.c/resource.c/schedobj.c + 4 trace .c, meson compiles all other scheduler_srcs as separate TUs; real plugin.c supplies plugin_* symbols (NO stubs in the test); this is how scheduler.c gets linked for sched_account_jobs without white-box including it. +- `src/scheduler/testsuite/test_reason_ownership_audit.c` (1fd6dc1c, 2026-10-30) — Phase 1: bug-1521 reason-ownership contract lock. Closed-list (51-file) scan for schedobj-shaped reason ownership + OWNERSHIP_SITES allowlist + sched_job_picker body scan (brace-matched). Exemptions: ctx->reason shuttle (sched_ctx_t local), construction =NULL, destruction frees, comment lines. In sched_unit_test aggregate. +- `.kiro/steering/scheduler-reason-ownership.md` (1fd6dc1c) — bug-1521 discipline as review reference: allocator thread = sole reason writer, picker never touches reasons, MOVE_PTR/free verbs, ctx->reason exemption, enforcement via the audit test. diff --git a/.wolf/memory.md b/.wolf/memory.md new file mode 100644 index 00000000..206969e0 --- /dev/null +++ b/.wolf/memory.md @@ -0,0 +1,7 @@ +# Memory Log + +- 2026-10-29: Delivered `scheduler-hardening-plan.md` (scheduler hardening, 5 phases, root of repo). Based on full source read of rejoin chain: controller sched.c on_scheduler_join push order (configs→workers→jobs), egress.c commit watermark, scheduler core_events.c merge semantics (14 accumulated bug fixes 1513-1886), core_session.c reset+re-derive (bug-1799), snapshot_load.c atomic-rebuild precedent, sched_election.c reason threading contract (91c3fb7f). Plan thesis: rejoin = atomic derived-state discard + full rebuild (state-level equivalence with fresh join), merge reserved for true incremental events. Zero open bugs currently (1971-1980 all fixed) — this is structural hardening, not bug fixing. +- 2026-10-30: Phase 0 test 1 landed (b20caf8d): test_res_account_symmetry.c 102/102 green, mutation-injection red proof done (removing resource.c bug-1801 skip → 2.5→4.5 = +1 charge/round exactly bug-1799 shape). Two semantic lessons from writing it: (1) charge formula = used+reserved where used is the OVERAGE component reconcile maintains (acct_entry->used ← max(0, actual - reserved), pool delta = new_used - old used), so pool converges to max(reserved, actual) — NOT "charge is the usage"; (2) charge-skip tests are vacuous unless the job's account NAMES the excluded host (one account entry per host, each its own struct+baseline). sched_repl_trace baseline single flake re-run green (known MALLOC_PERTURB_ mechanism, bug-1971). +- 2026-10-30 (later): Phase 0 fully closed. 0.2 rejoin-trigger contract audited — NO gap: 5 rejoin tests in test_scheduler_decision_publish_retry.c + test_scheduler_connect.c's no-io scan already lock the full contract (flag-only, broken-only, healthy no-probe, flag clear semantics, main.c unconditional call site). Plan doc updated with execution results (5269f8a5), branch pushed to myxce. Next: Phase 1 (bug-1521 reason-ownership structural scan + steering doc). +- 2026-10-30 (Phase 1): reason-ownership audit landed (1fd6dc1c, pushed). test_reason_ownership_audit.c: 51-file closed-list scan + OWNERSHIP_SITES allowlist (fragments verified live) + sched_job_picker body scan; ctx->reason shuttle exempt (sched_ctx_t local), construction =NULL + destruction free exempt, comment lines skipped (leading-marker test -- contract prose names the write shape). Injection red-proof: picker MOVE_PTR(job->schedobj->reason) tripped BOTH scans. Steering doc .kiro/steering/scheduler-reason-ownership.md created. Detector lessons: same-line discipline needs schedobj-base allowlist (ctx->reason false-positive), comment lines MUST be skipped (scheduler.c:496 comment itself has MOVE_PTR(obj->reason) inline). Next: Phase 2 (rejoin rebuild — user approved kiro spec workflow for it). +- 2026-10-30 (HA-impact analysis): Before Phase 2, user gated on a full HA-impact analysis. Source trace completed: rejoin trigger chain (client_failover.c xcecli_invoke_rejoin :213/:420 after transparent rotate → sched_on_reconnect flag, no-I/O constraint from failover.lock self-deadlock → sched_check_pending_rejoin scheduler.c:1871, main.c:550 unconditional + publish-loop call :1962); controller side (join.c:166 handle_scheduler_join → on_scheduler_join sched.c:792 pushes configs→workers→jobs, NO fence/role gate on the join opcode itself, jobs gated by egress.c job_submit_committed); receive side (handler.c enqueues everything as pend_updates → driver.c:713 translate batch between rounds → core_events.c merge; JOBS_PUSH duplicate-merge block ~245 lines is the 14-fix hot spot). Constraints found for rebuild design: xce_core_push_events is -EBUSY under session_active — rebuild must sit at the same between-rounds boundary as sched_apply_pending_config (main.c:520); limit plugin instance survival comes free via limit_replace_config/rebind_instances_ (bug-1884) as long as rebuild routes config through plugin config_cb; configver++ must be mirrored; capnp ReplayEvent.body union has additive ordinals 12+ available for the rejoin-boundary marker (schema comment at :1209 explicitly reserves additive growth). Analysis delivered to user; kiro spec workflow for Phase 2 next.