@polderlabs/bizar 10.7.0 → 10.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/.claude/agents/_shared/AGENT_BASELINE.md +266 -0
  2. package/.claude/agents/_shared/CLAUDE_TOOLS.md +412 -0
  3. package/.claude/agents/_shared/SKILLS.md +109 -0
  4. package/.claude/agents/brand-designer.md +55 -0
  5. package/.claude/agents/exec-assistant.md +34 -0
  6. package/.claude/agents/help-desk.md +44 -0
  7. package/.claude/agents/it-lead.md +53 -0
  8. package/.claude/agents/knowledge-manager.md +49 -0
  9. package/.claude/agents/office-coordinator.md +39 -0
  10. package/.claude/agents/office-greeter.md +53 -0
  11. package/.claude/agents/office-manager.md +287 -0
  12. package/.claude/agents/principal-engineer.md +58 -0
  13. package/.claude/agents/qa-reviewer.md +51 -0
  14. package/.claude/agents/research-analyst.md +53 -0
  15. package/.claude/agents/senior-engineer.md +55 -0
  16. package/.claude/agents/support-tech.md +87 -0
  17. package/.claude/agents/vp-engineering.md +54 -0
  18. package/.claude/commands/audit.md +48 -0
  19. package/.claude/commands/bizar.md +22 -0
  20. package/.claude/commands/cron.md +36 -0
  21. package/.claude/commands/explain.md +17 -0
  22. package/.claude/commands/goal.md +99 -0
  23. package/.claude/commands/init.md +15 -0
  24. package/.claude/commands/learn.md +46 -0
  25. package/.claude/commands/plan.md +35 -0
  26. package/.claude/commands/plow-through.md +50 -0
  27. package/.claude/commands/pr-review.md +49 -0
  28. package/.claude/commands/setup-provider.md +96 -0
  29. package/.claude/commands/spec.md +47 -0
  30. package/.claude/commands/sprint.md +43 -0
  31. package/.claude/commands/tailscale-serve.md +100 -0
  32. package/.claude/commands/team.md +132 -0
  33. package/.claude/commands/test.md +62 -0
  34. package/.claude/commands/validate.md +68 -0
  35. package/.claude/commands/visual-plan.md +24 -0
  36. package/.claude/hooks/README.md +108 -0
  37. package/.claude/hooks/__tests__/pretooluse-editwrite.test.mjs +146 -0
  38. package/.claude/hooks/__tests__/sessionend-recall.test.mjs +256 -0
  39. package/.claude/hooks/__tests__/sessionstart-prime.test.mjs +325 -0
  40. package/.claude/hooks/__tests__/thinking-route.test.mjs +319 -0
  41. package/.claude/hooks/auto-instinct.sh +81 -0
  42. package/.claude/hooks/learning-extract.mjs +92 -0
  43. package/.claude/hooks/post-merge-audit.sh +93 -0
  44. package/.claude/hooks/posttooluse-editwrite.mjs +91 -0
  45. package/.claude/hooks/pretooluse-bash.mjs +87 -0
  46. package/.claude/hooks/pretooluse-editwrite.mjs +117 -0
  47. package/.claude/hooks/sessionend-recall.mjs +384 -0
  48. package/.claude/hooks/sessionstart-prime.mjs +278 -0
  49. package/.claude/hooks/thinking-route.mjs +314 -0
  50. package/.claude/hooks/worker-suggest.mjs +110 -0
  51. package/.claude/settings.json +167 -0
  52. package/.claude/skills/9router/SKILL.md +80 -0
  53. package/.claude/skills/9router-chat/SKILL.md +73 -0
  54. package/.claude/skills/9router-embeddings/SKILL.md +69 -0
  55. package/.claude/skills/9router-image/SKILL.md +86 -0
  56. package/.claude/skills/9router-stt/SKILL.md +79 -0
  57. package/.claude/skills/9router-tts/SKILL.md +80 -0
  58. package/.claude/skills/9router-web-fetch/SKILL.md +99 -0
  59. package/.claude/skills/9router-web-search/SKILL.md +91 -0
  60. package/.claude/skills/agent-browser/SKILL.md +64 -0
  61. package/.claude/skills/bizar/README.md +9 -0
  62. package/.claude/skills/bizar/SKILL.md +447 -0
  63. package/.claude/skills/cpp-coding-standards/README.md +28 -0
  64. package/.claude/skills/cpp-coding-standards/SKILL.md +634 -0
  65. package/.claude/skills/cpp-coding-standards/references/concurrency.md +320 -0
  66. package/.claude/skills/cpp-coding-standards/references/error-handling.md +229 -0
  67. package/.claude/skills/cpp-coding-standards/references/memory-safety.md +216 -0
  68. package/.claude/skills/cpp-coding-standards/references/modern-idioms.md +282 -0
  69. package/.claude/skills/cpp-coding-standards/references/review-checklist.md +96 -0
  70. package/.claude/skills/cpp-testing/README.md +28 -0
  71. package/.claude/skills/cpp-testing/SKILL.md +304 -0
  72. package/.claude/skills/cpp-testing/references/coverage.md +370 -0
  73. package/.claude/skills/cpp-testing/references/framework-compare.md +175 -0
  74. package/.claude/skills/cpp-testing/references/host-test-for-embedded.md +499 -0
  75. package/.claude/skills/cpp-testing/references/mocking.md +364 -0
  76. package/.claude/skills/cpp-testing/references/tdd-workflow.md +308 -0
  77. package/.claude/skills/cubesandbox/SKILL.md +148 -0
  78. package/.claude/skills/de-sloppify/SKILL.md +38 -0
  79. package/.claude/skills/de-sloppify/cleanup.mjs +253 -0
  80. package/.claude/skills/de-sloppify/cleanup.test.mjs +189 -0
  81. package/.claude/skills/embedded-esp-idf/README.md +41 -0
  82. package/.claude/skills/embedded-esp-idf/SKILL.md +439 -0
  83. package/.claude/skills/embedded-esp-idf/references/freertos-patterns.md +214 -0
  84. package/.claude/skills/embedded-esp-idf/references/host-tests.md +164 -0
  85. package/.claude/skills/embedded-esp-idf/references/idf-py-commands.md +157 -0
  86. package/.claude/skills/embedded-esp-idf/references/kconfig.md +159 -0
  87. package/.claude/skills/embedded-esp-idf/references/logging-discipline.md +118 -0
  88. package/.claude/skills/embedded-esp-idf/references/memory-and-iram.md +137 -0
  89. package/.claude/skills/embedded-esp-idf/references/nvs.md +121 -0
  90. package/.claude/skills/embedded-esp-idf/references/packed-structs.md +192 -0
  91. package/.claude/skills/embedded-esp-idf/scripts/idf_env.sh +47 -0
  92. package/.claude/skills/embedded-esp-idf/scripts/size_check.sh +77 -0
  93. package/.claude/skills/glyph/SKILL.md +163 -0
  94. package/.claude/skills/harness-engineering/SKILL.md +142 -0
  95. package/.claude/skills/lightrag/SKILL.md +81 -0
  96. package/.claude/skills/memory-protocol/SKILL.md +105 -0
  97. package/.claude/skills/obsidian/SKILL.md +306 -0
  98. package/.claude/skills/read-the-damn-docs/SKILL.md +113 -0
  99. package/.claude/skills/self-improvement/SKILL.md +64 -0
  100. package/.claude/skills/skillopt/SKILL.md +129 -0
  101. package/.claude/skills/thinking-archetypes/SKILL.md +90 -0
  102. package/.claude/skills/thinking-bayesian/SKILL.md +267 -0
  103. package/.claude/skills/thinking-bounded-rationality/SKILL.md +406 -0
  104. package/.claude/skills/thinking-circle-of-competence/SKILL.md +216 -0
  105. package/.claude/skills/thinking-cynefin/SKILL.md +70 -0
  106. package/.claude/skills/thinking-debiasing/SKILL.md +192 -0
  107. package/.claude/skills/thinking-dual-process/SKILL.md +282 -0
  108. package/.claude/skills/thinking-effectuation/SKILL.md +366 -0
  109. package/.claude/skills/thinking-feedback-loops/SKILL.md +464 -0
  110. package/.claude/skills/thinking-fermi-estimation/SKILL.md +263 -0
  111. package/.claude/skills/thinking-first-principles/SKILL.md +167 -0
  112. package/.claude/skills/thinking-five-whys-plus/SKILL.md +139 -0
  113. package/.claude/skills/thinking-inversion/SKILL.md +195 -0
  114. package/.claude/skills/thinking-jobs-to-be-done/SKILL.md +363 -0
  115. package/.claude/skills/thinking-kepner-tregoe/SKILL.md +154 -0
  116. package/.claude/skills/thinking-leverage-points/SKILL.md +390 -0
  117. package/.claude/skills/thinking-lindy-effect/SKILL.md +331 -0
  118. package/.claude/skills/thinking-map-territory/SKILL.md +111 -0
  119. package/.claude/skills/thinking-margin-of-safety/SKILL.md +330 -0
  120. package/.claude/skills/thinking-model-combination/SKILL.md +406 -0
  121. package/.claude/skills/thinking-model-router/SKILL.md +360 -0
  122. package/.claude/skills/thinking-model-selection/SKILL.md +341 -0
  123. package/.claude/skills/thinking-occams-razor/SKILL.md +129 -0
  124. package/.claude/skills/thinking-ooda/SKILL.md +127 -0
  125. package/.claude/skills/thinking-opportunity-cost/SKILL.md +360 -0
  126. package/.claude/skills/thinking-pre-mortem/SKILL.md +170 -0
  127. package/.claude/skills/thinking-probabilistic/SKILL.md +324 -0
  128. package/.claude/skills/thinking-red-team/SKILL.md +142 -0
  129. package/.claude/skills/thinking-regret-minimization/SKILL.md +335 -0
  130. package/.claude/skills/thinking-reversibility/SKILL.md +326 -0
  131. package/.claude/skills/thinking-scientific-method/SKILL.md +162 -0
  132. package/.claude/skills/thinking-second-order/SKILL.md +184 -0
  133. package/.claude/skills/thinking-socratic/SKILL.md +198 -0
  134. package/.claude/skills/thinking-steel-manning/SKILL.md +332 -0
  135. package/.claude/skills/thinking-systems/SKILL.md +238 -0
  136. package/.claude/skills/thinking-theory-of-constraints/SKILL.md +338 -0
  137. package/.claude/skills/thinking-thought-experiment/SKILL.md +354 -0
  138. package/.claude/skills/thinking-triz/SKILL.md +171 -0
  139. package/.claude/skills/thinking-via-negativa/SKILL.md +358 -0
  140. package/bizar-dash/skills/publishing/SKILL.md +2 -1
  141. package/cli/install/postinstall.mjs +54 -28
  142. package/cli/install/postinstall.test.mjs +98 -0
  143. package/cli/provision.mjs +29 -0
  144. package/install.sh +7 -0
  145. package/package.json +7 -2
  146. package/scripts/git-hooks/__tests__/commit-msg.test.mjs +61 -0
  147. package/scripts/git-hooks/commit-msg +38 -0
  148. package/scripts/install-hooks.sh +9 -0
@@ -0,0 +1,100 @@
1
+ ---
2
+ description: Authenticate Tailscale Serve and expose a local port on your tailnet
3
+ allowed-tools: Read, Bash
4
+ ---
5
+
6
+ # Tailscale Serve Command
7
+
8
+ Authenticate and configure Tailscale Serve to expose a local service on your
9
+ tailnet. Auto-detects whether Serve is enabled on the tailnet and either
10
+ provisions HTTPS automatically or surfaces the admin-enable URL clearly.
11
+
12
+ ## Usage
13
+
14
+ ```
15
+ /tailscale-serve # expose port 8765 (the BizarHarness dashboard default)
16
+ /tailscale-serve 3000 # expose port 3000
17
+ /tailscale-serve --status # show current serve config, no changes
18
+ /tailscale-serve --reset # remove the current serve config
19
+ ```
20
+
21
+ The full arguments are available as `$ARGUMENTS` (and `$1` for the port).
22
+ Parse them and route to the matching step below.
23
+
24
+ ## Steps
25
+
26
+ 1. **Parse the argument**: first arg is the port (default `8765`). If `--status`, run step 3 only. If `--reset`, run step 6 only.
27
+
28
+ 2. **Verify the local port is listening**:
29
+ ```bash
30
+ ss -lntp 2>/dev/null | grep -E ":${PORT}\b" || curl -sS -o /dev/null -w "HTTP %{http_code}\n" --max-time 2 http://127.0.0.1:${PORT}/
31
+ ```
32
+ If the port is not open, tell the user clearly which command starts the
33
+ service (e.g. `npm run host:start` for the BizarHarness demo, or
34
+ `python3 -m http.server 8765` for a pam static server). Do not proceed
35
+ without an upstream.
36
+
37
+ 3. **Check current Tailscale Serve status**:
38
+ ```bash
39
+ tailscale serve status
40
+ tailscale status --json | jq -r '.Self.DNSName, .Self.TailscaleIPs[0]'
41
+ ```
42
+ Capture the MagicDNS name and the Tailscale IP. The DNS name will look
43
+ like `devbox.tail2cdf4d.ts.net` (trim the trailing dot).
44
+
45
+ 4. **If already configured** (status shows `https://`):
46
+ - Print the current config
47
+ - Print the existing endpoints
48
+ - **Stop** — do not re-configure
49
+
50
+ 5. **Try to enable Serve** (with a hard timeout — it may try to open a browser):
51
+ ```bash
52
+ timeout 5 tailscale serve --bg --https=443 "http://127.0.0.1:${PORT}" 2>&1
53
+ ```
54
+ - **On success**: print the new config, print the `https://<dnsname>/` endpoint.
55
+ - **If the output contains "Serve is not enabled"**:
56
+ - Parse the admin-enable URL from the output (it's the
57
+ `https://login.tailscale.com/f/serve?node=...` line).
58
+ - Print it prominently with a clear message:
59
+ > **Tailscale Serve is not enabled on this tailnet.**
60
+ > An admin must visit this URL once to enable it:
61
+ > **<URL>**
62
+ > Then re-run `/tailscale-serve ${PORT}`.
63
+ - Do not fall back to plain HTTP automatically — the user asked for
64
+ authentication, not a workaround. They can run the demo's
65
+ `host:start` script for the HTTP fallback.
66
+ - **On any other error**: print the full error, suggest
67
+ `tailscale serve status` and `sudo tailscale up` as debug steps.
68
+
69
+ 6. **For `--reset`**:
70
+ ```bash
71
+ tailscale serve reset
72
+ ```
73
+ Confirm the reset succeeded by re-running `tailscale serve status`.
74
+
75
+ 7. **Final output** — always end with a clear status block:
76
+
77
+ ```
78
+ === Tailscale Serve ===
79
+ config: <status>
80
+ upstream: http://127.0.0.1:<port>
81
+ endpoints:
82
+ - https://<dnsname>/ (HTTPS, only if Serve is enabled)
83
+ - http://<dnsname>:<port>/ (HTTP fallback, only if upstream binds 0.0.0.0)
84
+
85
+ To remove: /tailscale-serve --reset
86
+ ```
87
+
88
+ ## Notes
89
+
90
+ - `tailscale serve` requires a one-time tailnet admin enable. There is no
91
+ per-device flag — only the admin can authorize it. The command surfaces
92
+ the admin URL and stops rather than silently falling back.
93
+ - This command does not start the upstream service. It assumes the service
94
+ is already running and only wires the HTTPS proxy.
95
+ - For the BizarHarness Demo Dashboard, the typical flow is:
96
+ ```
97
+ /tailscale-serve --status # see current state
98
+ npm run host:start # upstream on port 8765
99
+ /tailscale-serve # expose it on the tailnet
100
+ ```
@@ -0,0 +1,132 @@
1
+ ---
2
+ description: Spawn a Claude Code agent team — coordinate Thor (M2.7), Tyr (M3), Mimir (research), and Hermod (git) to complete a complex mission end-to-end.
3
+ allowed-tools: Read, Bash, Agent
4
+ ---
5
+
6
+ # Team — Spawn a Claude Code Agent Team
7
+
8
+ The `/team` command spawns a **coordinated agent team** for a complex,
9
+ multi-step mission. The lead agent coordinates teammates; each teammate
10
+ owns a disjoint scope; results are synthesized and committed.
11
+
12
+ The full mission is available as `$ARGUMENTS` (or composed from `$1`).
13
+
14
+ ## When to Use `/team`
15
+
16
+ Use `/team` for any non-trivial mission that benefits from **parallel
17
+ work + explicit coordination**. Examples:
18
+
19
+ - **Refactor** — split a module across Thor (M2.7) and Tyr (M3) in parallel.
20
+ - **Multi-feature build** — new feature A (Thor) + new feature B (Tyr) + tests (Heimdall).
21
+ - **Research + implementation** — Mimir researches, Thor implements, Forseti audits.
22
+ - **Migration / upgrade** — Hermod handles the git/PR lifecycle while Thor/Tyr write code.
23
+ - **Bug hunt** — Mimir traces the data flow while Tyr writes the fix and tests.
24
+
25
+ Do NOT use `/team` for trivial single-file edits or single-question
26
+ clarifications. Use `@brenda` directly for those.
27
+
28
+ ## Default Team Composition
29
+
30
+ If the user does not specify a team composition, spawn this default:
31
+
32
+ | Role | Agent | Model | Job |
33
+ |---------------|---------|-------------------|---------------------------------------|
34
+ | Lead | @mike | minimax/MiniMax-M3 | Coordinate, synthesize, gate quality |
35
+ | Implementer 1 | @todd | minimax/MiniMax-M2.7 | Moderate-complexity implementation |
36
+ | Implementer 2 | @karen | minimax/MiniMax-M3 | Complex / cross-cutting work |
37
+ | Researcher | @greg | bizar/MiniMax-M3 | Codebase research, pattern discovery |
38
+ | Git ops | @steve | minimax/MiniMax-M2.7 | Branch, commit, push, PR |
39
+ | Reviewer | @linda| minimax/MiniMax-M3 | Audit plan + final output |
40
+
41
+ You can swap or remove any of these — but always keep at least one
42
+ implementer and a reviewer.
43
+
44
+ ## Protocol (How Odin Runs a `/team` Invocation)
45
+
46
+ 1. **Read `.bizar/PROJECT.md`** if it exists. Factor the project
47
+ description into the team mission.
48
+ 2. **Read `bizar memory status`**. If the vault is reachable, run
49
+ `bizar memory search "<topic>"` for prior context on the mission.
50
+ 3. **Decompose** the mission into disjoint work items. Each item
51
+ names:
52
+ - The agent that owns it
53
+ - The file scope (paths/globs)
54
+ - The deliverable (a function, a test, a commit, a doc)
55
+ - The exit signal ("done when X is committed")
56
+ 4. **Launch in parallel** — use the **Agent tool** in a **single
57
+ message** with multiple `Agent` calls so all teammates run
58
+ concurrently. Each call's prompt names the Bizar agent
59
+ (`todd`, `karen`, `greg`, `steve`, `linda`) so the audit
60
+ trail stays readable. For long-running work, pass
61
+ `run_in_background: true`.
62
+ 5. **Monitor** — while the team runs, return control to the user.
63
+ The team runs asynchronously. Check teammate progress only
64
+ when the user asks (use `SendMessage` to the named agent).
65
+ 6. **Synthesize** — when teammates report back, gate through @linda
66
+ (audit) and @steve (commit/push). Then report the final outcome
67
+ to the user with file:line references.
68
+
69
+ ## Pre-Dispatch Checklist (MANDATORY)
70
+
71
+ - [ ] Each teammate has a **disjoint file scope** — no two agents
72
+ edit the same file or directory
73
+ - [ ] Lockfiles, `package.json`, root configs, `tsconfig.json`,
74
+ `vite.config.*`, `Dockerfile`, CI configs are assigned to ONE
75
+ agent or marked READ-ONLY for everyone else
76
+ - [ ] No subagent has both `bash: allow` AND a write-level git task
77
+ in the same batch — Hermod is the only git writer
78
+ - [ ] Each teammate's scope is named in plain English
79
+ - [ ] You have prepended a one-paragraph sibling-awareness block to
80
+ every prompt (Odin baseline, "Parallel Dispatch Coordination")
81
+ - [ ] You have called `bizar memory status` and confirmed the vault
82
+ is reachable
83
+
84
+ ## Example Mission Strings
85
+
86
+ **Refactor a module:**
87
+ ```
88
+ Refactor src/api/auth.ts into a clean module: extract JWT validation
89
+ into src/auth/jwt.ts, rate-limiting into src/auth/rate-limit.ts, and
90
+ keep the public surface stable. Add tests for each new module. Update
91
+ docs/architecture.md with the new module map. Do not change the HTTP
92
+ route handlers.
93
+ ```
94
+
95
+ **Multi-feature build:**
96
+ ```
97
+ Add a kanban board: (1) Thor — backend API at /api/tasks with CRUD
98
+ endpoints and SQLite persistence. (2) Tyr — frontend React component
99
+ in src/components/Kanban.tsx with 5 columns. (3) Heimdall — write
100
+ the OpenAPI spec at docs/api/tasks.yaml. (4) Hermod — open a PR
101
+ named feat/kanban-board.
102
+ ```
103
+
104
+ **Bug hunt:**
105
+ ```
106
+ Mimir — trace the data flow from POST /api/checkout through to the
107
+ Stripe webhook handler; find any place where the order status is
108
+ written before the payment is confirmed. Tyr — write a regression
109
+ test that reproduces the race. Thor — fix the bug. Forseti —
110
+ audit the fix for completeness. Hermod — commit + push.
111
+ ```
112
+
113
+ ## Tool Reference (Claude Code)
114
+
115
+ - **Agent tool** — spawn one subagent per call. Use multiple
116
+ `Agent` calls in a single message for parallelism.
117
+ - `run_in_background: true` on the Agent tool — for tasks that
118
+ span more than a few minutes.
119
+ - `SendMessage` — talk to a running background agent by name.
120
+
121
+ ## Failure Modes
122
+
123
+ - **Two agents write the same file** — STOP, revert one branch, reassign.
124
+ - **One agent stalls** — use `TaskStop` to terminate, route the
125
+ remaining scope to another agent.
126
+ - **Tests fail after team work** — dispatch `todd` to investigate;
127
+ do not paper over the failure.
128
+ - **Git conflict** — route to `steve` for `git rebase` / merge
129
+ resolution.
130
+ - **A teammate goes silent** — send a `SendMessage` to the named
131
+ agent for a status report; if dead, kill and re-spawn with a
132
+ fresh prompt.
@@ -0,0 +1,62 @@
1
+ ---
2
+ description: Run the project's test suite via the Bizar test gate. Auto-detects jest/vitest/bun/pytest/cargo/go. Exits non-zero on failure.
3
+ allowed-tools: Read, Bash
4
+ ---
5
+
6
+ # /test — Run the Project's Test Suite
7
+
8
+ The `/test` command is a thin wrapper around `bizar test-gate`. It
9
+ auto-detects the project's test runner and runs the full suite.
10
+
11
+ ## What It Does
12
+
13
+ 1. Detects the project stack (one of: npm, pytest, cargo, go).
14
+ 2. Runs the matching test command:
15
+ - `package.json` present → `npm test`
16
+ - `pyproject.toml` present → `pytest`
17
+ - `Cargo.toml` present → `cargo test`
18
+ - `go.mod` present → `go test ./...`
19
+ 3. Streams the test output to the user.
20
+ 4. Exits non-zero on test failures.
21
+
22
+ ## Exit Codes
23
+
24
+ | Code | Meaning |
25
+ |------|----------------------------------|
26
+ | 0 | All tests passed |
27
+ | 1 | Tests failed |
28
+ | 2 | No test runner detected |
29
+
30
+ ## How to Use
31
+
32
+ Invoke `/test` from the project root. The test gate inspects the
33
+ current directory and picks the right runner.
34
+
35
+ To run a specific Bizar test scope instead, pass arguments to
36
+ `/test`. The arguments are forwarded to the underlying runner and
37
+ are available as `$ARGUMENTS` (or `$1`, `$2`, ...):
38
+
39
+ - `/test plugins/bizar` — run only the Bizar plugin tests (bun)
40
+ - `/test --testPathPattern=auth` — pass a flag to the runner
41
+
42
+ ## When to Use
43
+
44
+ - After any non-trivial code change
45
+ - Before committing (`@steve` should always run `/test` first)
46
+ - As the final step of a `/team` mission — gate quality with tests
47
+
48
+ ## Common Patterns
49
+
50
+ - **Post-implementation gate** — after Thor and Tyr finish their
51
+ parallel work, dispatch `todd` to run `/test`. If failures, fix
52
+ and re-run.
53
+ - **PR check** — run `/test` in CI before merging.
54
+ - **Debug a flaky test** — run `/test` twice; if the second run
55
+ passes, the test is order-dependent (fix or quarantine).
56
+
57
+ ## Related
58
+
59
+ - `bizar test-gate` — the underlying CLI command
60
+ - `bizar doctor` — checks the Bizar install itself (not project tests)
61
+ - `make check` — typecheck + tests (full pipeline, dev only)
62
+ - `make e2e` — Bizar plugin end-to-end (dev only)
@@ -0,0 +1,68 @@
1
+ ---
2
+ description: Validate the Bizar install end-to-end — settings.json parses, plugin entry resolves, all agent files are installed, all skills/rules/hooks/commands are in place, provider config is sane, and the 9router gateway is reachable.
3
+ allowed-tools: Read, Bash
4
+ ---
5
+
6
+ # /validate — Validate the Bizar Install
7
+
8
+ The `/validate` command runs `bizar doctor` with the full check
9
+ battery. It is the fastest way to confirm the install is healthy
10
+ and Claude Code will see every Bizar component on the next session
11
+ start.
12
+
13
+ ## What It Checks
14
+
15
+ 1. **claude-reachable** — `claude --version` exits 0.
16
+ 2. **claude-config-valid** — `~/.claude/settings.json` parses as JSON.
17
+ 3. **plugin-entry-present** — `settings.json` has a Bizar plugin entry.
18
+ 4. **plugin-path-resolves** — the plugin path on disk actually exists.
19
+ 5. **agent-files-installed** — all agent files in `~/.claude/agents/`
20
+ (mike, janet, susan, pam, greg, brenda, steve, todd, brad,
21
+ karen, carl, linda, oscar, kevin).
22
+ 6. **tools-available** — at least one of `semble`, `skills`
23
+ is on PATH.
24
+ 7. **provider-config-sanity** — `provider.9router` has at least
25
+ one sane model entry.
26
+ 8. **9router-reachable** — 9Router gateway responds at
27
+ `http://localhost:20128/health` (lenient — warn, don't fail).
28
+ 9. **slash-commands-installed** — all Bizar slash commands
29
+ (`/audit`, `/explain`, `/init`, `/learn`, `/plan`, `/plow-through`,
30
+ `/pr-review`, `/tailscale-serve`, `/visual-plan`, `/bizar`,
31
+ `/team`, `/test`, `/validate`) are present in `~/.claude/commands/`.
32
+ 10. **skills-installed** — every subdir of `config/skills/` is
33
+ mirrored to `~/.claude/skills/`.
34
+ 11. **rules-installed** — every `.md` in `config/rules/` is mirrored
35
+ to `~/.claude/rules/`.
36
+ 12. **hooks-installed** — `.claude/hooks/` scripts are installed
37
+ with executable permissions.
38
+
39
+ ## How to Use
40
+
41
+ Invoke `/validate` (no arguments) from anywhere. It is read-only and
42
+ never modifies the system.
43
+
44
+ If any check fails, the user should run `bizar update` to refresh the
45
+ install, or `bizar repair` to fix common issues.
46
+
47
+ ## Output
48
+
49
+ Each check prints ✓ or ✗ with a one-line message. The summary line
50
+ shows the total pass/fail count. Exits non-zero if any check fails.
51
+
52
+ For machine-readable output, the user can run `bizar doctor --json`
53
+ directly.
54
+
55
+ ## When to Use
56
+
57
+ - After a manual config edit — confirm nothing broke.
58
+ - Before a `/team` mission — confirm the install is healthy so the
59
+ team has all the tools it needs.
60
+ - After `bizar install` or `bizar update` — the install already
61
+ calls doctor, but a manual re-run is cheap.
62
+ - When a user asks "why is Claude Code misbehaving?" — start here.
63
+
64
+ ## Related
65
+
66
+ - `bizar doctor` — the underlying CLI command
67
+ - `bizar update` — refreshes the install (re-runs syncConfigExtras)
68
+ - `bizar repair` — fixes common issues (stale symlinks, version drift)
@@ -0,0 +1,24 @@
1
+ ---
2
+ description: Toggle the Bizar visual plan canvas or check its current status.
3
+ ---
4
+
5
+ # /visual-plan — Toggle Visual Plan Canvas
6
+
7
+ Toggle the Bizar visual plan canvas or check its current status.
8
+
9
+ The full arguments are available as `$ARGUMENTS` (and `$1`).
10
+
11
+ ## Usage
12
+
13
+ ```
14
+ /visual-plan on — Enable the visual plan canvas in the current session
15
+ /visual-plan off — Disable the visual plan canvas
16
+ /visual-plan status — Show whether the canvas is currently enabled
17
+ ```
18
+
19
+ ## Notes
20
+
21
+ The visual plan canvas shows plans as interactive node graphs. When enabled, plan elements appear as draggable nodes on a canvas that agents can manipulate directly. This is useful for visual thinkers or when planning complex multi-step work.
22
+
23
+ This is a session-level toggle — it affects the current Claude Code
24
+ session only.
@@ -0,0 +1,108 @@
1
+ # Bizar Harness — Claude Code Hooks
2
+
3
+ This directory contains the **Claude Code** adapter scripts that back the
4
+ project-scoped hooks defined in `.claude/settings.json`.
5
+
6
+ They replaced the legacy Cline hooks. The Claude Code
7
+ set is the only supported path on Bizar v6.3.0+; the legacy Cline hooks
8
+ are no longer installed.
9
+
10
+ ## Adapter inventory
11
+
12
+ | File | Event | Matcher | Behaviour |
13
+ |------|-------|---------|-----------|
14
+ | `pretooluse-editwrite.mjs` | `PreToolUse` | `Write\|Edit\|MultiEdit\|Bash` | Blocks `.env`/secrets/lockfiles; warns on `console.log`/`debugger`/`.only()` in `src/`; scans `Bash` against the 36-pattern dangerous-pattern list |
15
+ | `posttooluse-editwrite.mjs` | `PostToolUse` | `Edit\|Write\|MultiEdit` | Logs edit/write latency + size to `~/.config/bizar/hook-logs/` |
16
+ | `sessionstart-prime.mjs` | `SessionStart` | (none — branches on `source`) | Reads PROGRESS.md + feature_list.json + git log + .bizar/PROJECT.md; branches on `startup`/`clear`/`resume`; WIP=1 guard |
17
+ | `thinking-route.mjs` | `UserPromptSubmit` | (none) | Slash-command routing (team/plow-through/test/validate/plan/audit/pr-review) + 35-bucket thinking-* mental-model router |
18
+ | `worker-suggest.mjs` | `UserPromptSubmit` | (none) | Calls `cli/worker-dispatcher.mjs:dispatch()` against `config/trigger-patterns.json` |
19
+ | `sessionend-recall.mjs` | `SessionEnd` | (none) | Reads `transcript_path`; writes `.bizar/sessions/<date>-<id>.md` + `.bizar/session-state.json` handoff |
20
+
21
+ ## SessionStart ↔ SessionEnd handoff
22
+
23
+ The two lifecycle hooks form a state machine via the `.bizar/session-state.json`
24
+ file:
25
+
26
+ ```
27
+ SessionEnd (session N)
28
+ ↓ writes .bizar/session-state.json with {nextStep, blockers, filesTouched}
29
+ SessionStart (session N+1, source: "resume")
30
+ ↑ reads it; primes the agent with "Last nextStep: …" + blockers
31
+ ```
32
+
33
+ If `.bizar/session-state.json` is missing, the resume branch degrades
34
+ gracefully to "No prior session-state.json found — treating as fresh start."
35
+
36
+ ## I/O contract
37
+
38
+ Claude Code invokes each hook as a child process, pipes JSON on
39
+ **stdin**, and reads JSON on **stdout**. The five adapters above all
40
+ read using `process.stdin` and write a single JSON object to
41
+ `process.stdout`.
42
+
43
+ ### Stdin (varies by event)
44
+
45
+ ```jsonc
46
+ // PreToolUse
47
+ {
48
+ "session_id": "...",
49
+ "transcript_path": "...",
50
+ "cwd": "/home/drb0rk/Projects/BizarHarness",
51
+ "hook_event_name": "PreToolUse",
52
+ "tool_name": "Write",
53
+ "tool_input": { "file_path": "/path", "content": "..." }
54
+ }
55
+
56
+ // PostToolUse (adds tool_response)
57
+ // UserPromptSubmit (uses .user_prompt instead of .tool_name/.tool_input)
58
+ // SessionStart (uses .source = "startup" | "resume" | "clear")
59
+ // SessionEnd (uses .reason = "exit" | "clear" | "logout" | "prompt_input_exit")
60
+ ```
61
+
62
+ ### Stdout
63
+
64
+ ```jsonc
65
+ // Block (PreToolUse only)
66
+ {
67
+ "hookSpecificOutput": {
68
+ "hookEventName": "PreToolUse",
69
+ "permissionDecision": "deny",
70
+ "permissionDecisionReason": "..."
71
+ }
72
+ }
73
+
74
+ // Inject context for the next turn (all events)
75
+ {
76
+ "hookSpecificOutput": {
77
+ "hookEventName": "PostToolUse", // or PreToolUse / SessionStart / UserPromptSubmit
78
+ "additionalContext": "..."
79
+ }
80
+ }
81
+ ```
82
+
83
+ For a non-blocking `PreToolUse`, omitting `permissionDecision` and
84
+ emitting only `additionalContext` is a soft hint to the model — the
85
+ tool call still proceeds.
86
+
87
+ ## Claude Code lifecycle mapping
88
+
89
+ The legacy Cline plugin used four separate events (PreToolUse,
90
+ PostToolUse, TaskStart, TaskResume, UserPromptSubmit). Claude Code
91
+ collapses "task start" and "task resume" into a single `SessionStart`
92
+ event that branches on `source` (`startup`, `resume`, `clear`). The
93
+ adapter `sessionstart-prime.mjs` reads `source` and applies the
94
+ appropriate priming logic for each branch.
95
+
96
+ ## Disabling an individual hook
97
+
98
+ Easiest path: comment out the matching `hooks` array entry in
99
+ `.claude/settings.json`. Removing the executable bit
100
+ (`chmod -x …`) also works — Claude Code silently skips hooks it can't
101
+ execute.
102
+
103
+ ## See also
104
+
105
+ - `cli/provision-claude.mjs` — installs Claude Code hooks to
106
+ `~/.claude/hooks/` and wires them via `~/.claude/settings.json`.
107
+ - `.claude/settings.json` — the project hook wiring
108
+ - `.bizar/session-state.json` — handoff artifact between SessionEnd and SessionStart
@@ -0,0 +1,146 @@
1
+ #!/usr/bin/env node
2
+ // Test suite for .claude/hooks/pretooluse-editwrite.mjs
3
+ //
4
+ // Invokes the hook with a synthetic Claude Code PreToolUse payload over
5
+ // stdin, captures stdout, and asserts on `permissionDecision`.
6
+ //
7
+ // Run: node --test .claude/hooks/__tests__/pretooluse-editwrite.test.mjs
8
+
9
+ 'use strict';
10
+
11
+ import { test } from 'node:test';
12
+ import assert from 'node:assert/strict';
13
+ import { spawnSync } from 'node:child_process';
14
+ import path from 'node:path';
15
+ import { fileURLToPath } from 'node:url';
16
+
17
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
18
+ const HOOK = path.resolve(__dirname, '..', 'pretooluse-editwrite.mjs');
19
+
20
+ function runHook(toolName, filePath) {
21
+ const payload = JSON.stringify({
22
+ session_id: 'test-session',
23
+ cwd: '/tmp',
24
+ hook_event_name: 'PreToolUse',
25
+ tool_name: toolName,
26
+ tool_input: toolName === 'Write'
27
+ ? { file_path: filePath, content: '' }
28
+ : toolName === 'Edit'
29
+ ? { file_path: filePath, new_string: '' }
30
+ : { file_path: filePath, edits: [] },
31
+ });
32
+ const result = spawnSync('node', [HOOK], { input: payload, encoding: 'utf8' });
33
+ if (result.status !== 0) {
34
+ throw new Error(`hook exited ${result.status}\nstderr: ${result.stderr}`);
35
+ }
36
+ const out = result.stdout.trim();
37
+ if (!out || out === '{}') return { decision: null, context: null };
38
+ const parsed = JSON.parse(out);
39
+ return {
40
+ decision: parsed.hookSpecificOutput?.permissionDecision ?? null,
41
+ reason: parsed.hookSpecificOutput?.permissionDecisionReason ?? null,
42
+ context: parsed.hookSpecificOutput?.additionalContext ?? null,
43
+ };
44
+ }
45
+
46
+ test('Write .env → deny', () => {
47
+ const r = runHook('Write', '/repo/.env');
48
+ assert.equal(r.decision, 'deny');
49
+ });
50
+
51
+ test('Write .env.local → deny', () => {
52
+ const r = runHook('Write', '/repo/.env.local');
53
+ assert.equal(r.decision, 'deny');
54
+ });
55
+
56
+ test('Write .env.production → deny', () => {
57
+ const r = runHook('Write', '/repo/.env.production');
58
+ assert.equal(r.decision, 'deny');
59
+ });
60
+
61
+ test('Write .envrc → deny', () => {
62
+ const r = runHook('Write', '/repo/.envrc');
63
+ assert.equal(r.decision, 'deny');
64
+ });
65
+
66
+ test('Write .env.example → allow (docs)', () => {
67
+ const r = runHook('Write', '/repo/research/gstack/.env.example');
68
+ assert.notEqual(r.decision, 'deny');
69
+ assert.match(r.context, /Bizar PreToolUse/);
70
+ });
71
+
72
+ test('Write .env.sample → allow (docs)', () => {
73
+ const r = runHook('Write', '/repo/templates/.env.sample');
74
+ assert.notEqual(r.decision, 'deny');
75
+ });
76
+
77
+ test('Write .env.template → allow (docs)', () => {
78
+ const r = runHook('Write', '/repo/templates/deploy/docker/.env.template');
79
+ assert.notEqual(r.decision, 'deny');
80
+ });
81
+
82
+ test('Write secrets/api.json → deny', () => {
83
+ const r = runHook('Write', '/repo/secrets/api.json');
84
+ assert.equal(r.decision, 'deny');
85
+ });
86
+
87
+ test('Write credentials/x.json → deny', () => {
88
+ const r = runHook('Write', '/repo/credentials/x.json');
89
+ assert.equal(r.decision, 'deny');
90
+ });
91
+
92
+ test('Write node_modules/x.js → deny', () => {
93
+ const r = runHook('Write', '/repo/node_modules/x.js');
94
+ assert.equal(r.decision, 'deny');
95
+ });
96
+
97
+ test('Write bun.lock → allow (package-manager output)', () => {
98
+ const r = runHook('Write', '/repo/bun.lock');
99
+ assert.notEqual(r.decision, 'deny');
100
+ });
101
+
102
+ test('Write bun.lockb → allow (binary lock variant)', () => {
103
+ const r = runHook('Write', '/repo/bun.lockb');
104
+ assert.notEqual(r.decision, 'deny');
105
+ });
106
+
107
+ test('Write package-lock.json → allow (package-manager output)', () => {
108
+ const r = runHook('Write', '/repo/package-lock.json');
109
+ assert.notEqual(r.decision, 'deny');
110
+ });
111
+
112
+ test('Write yarn.lock → allow', () => {
113
+ const r = runHook('Write', '/repo/yarn.lock');
114
+ assert.notEqual(r.decision, 'deny');
115
+ });
116
+
117
+ test('Write pnpm-lock.yaml → allow', () => {
118
+ const r = runHook('Write', '/repo/pnpm-lock.yaml');
119
+ assert.notEqual(r.decision, 'deny');
120
+ });
121
+
122
+ test('Write src/index.ts → allow + neutral context', () => {
123
+ const r = runHook('Write', '/repo/src/index.ts');
124
+ assert.notEqual(r.decision, 'deny');
125
+ assert.match(r.context, /tool=Write/);
126
+ assert.match(r.context, /path=\/repo\/src\/index\.ts/);
127
+ // No debug-artifact warning in the hook context line anymore.
128
+ assert.doesNotMatch(r.context, /console\.log/);
129
+ assert.doesNotMatch(r.context, /Heads up/);
130
+ });
131
+
132
+ test('Edit .env → deny (same rule applies to Edit)', () => {
133
+ const r = runHook('Edit', '/repo/.env');
134
+ assert.equal(r.decision, 'deny');
135
+ });
136
+
137
+ test('MultiEdit .env.example → allow (docs)', () => {
138
+ const r = runHook('MultiEdit', '/repo/.env.example');
139
+ assert.notEqual(r.decision, 'deny');
140
+ });
141
+
142
+ test('Unknown tool → no decision (silent pass)', () => {
143
+ const r = runHook('Bash', '/repo/.env');
144
+ // PreToolUse:Bash is handled by a separate hook — this one is a no-op.
145
+ assert.equal(r.decision, null);
146
+ });