maruda Full Harness Setup (Interview Mode)
Goal
Turn the current repository into a project that runs the
Diagnose → Register/Draft → Plan → Resolve ⇄ Verify cycle with
mechanical guardrails (hooks) and a lean CLAUDE.md.
Skills alone are L1. This setup adds L2–L3: a short project brain
(CLAUDE.md), hard rails (hooks + settings), and cycle guidance (rules).
It never creates scheduled or cron-driven automation (L4); event-driven
GitHub Actions — strict CI and the opt-in PR Agent review — are L2–L3 and
in scope.
Principles
- Interview, no auto-detection. Do NOT infer languages from
go.mod,
package.json, etc., even when they exist. This setup targets
pre-development projects where detection misleads. File existence is
used only for overwrite/merge prompts.
- Never overwrite existing CLAUDE.md / settings / hooks without
explicit per-file approval. Prefer merge (append missing sections).
- Hooks enforce hard rules; CLAUDE.md holds soft guidance. Keep
CLAUDE.md short — detail lives in skills and
.claude/rules/.
- Write files only after the user approves the Phase 4 summary.
Workflow
Ask one phase at a time and wait for answers. If the user says
"use defaults", still require the primary language choice, then apply
the defaults table below to everything else.
How to ask (question-tool contract)
When a structured question tool (e.g. AskUserQuestion) is available, use one
call per phase, and keep every call within the tool's contract — violating it
aborts the turn with "Invalid tool parameters":
- At most 4 questions per call; every question needs 2–4 predefined
options — never an empty or single-option list. A free-text "Other"
choice is provided by the tool automatically; rely on it for custom values
instead of inventing an "enter manually" option list.
- Free-form items (project name, custom commands) must still offer 2+
options: make option 1 the recommended default (e.g. "Use directory name:
- Multi-choice items (additional languages, components) use the tool's
multi-select mode.
- If the tool is unavailable or returns an error, fall back to asking the
same questions as plain chat text and wait for the answers — never skip a
phase because the tool failed.
Phase 0 — Preconditions
- Confirm the target is a git repository (offer
git init if not).
- Check existence (existence only — do not read to guess the stack) of:
CLAUDE.md, .claude/settings.json, .claude/hooks/,
.claude/rules/maruda-cycle.md, .claude/skills/.
- Tell the user: existing files will each get an overwrite/merge/skip
question in Phase 3.
Phase 1 — Project skeleton (required)
- Q1. Project name — options: "Use directory name: (Recommended)" /
"Use repository name" (custom names come via Other).
- Q2. Primary language (choose exactly one):
Go / Python / TypeScript / JavaScript.
- Q3. Additional languages (multi-select) — none, or any others from the
same list.
- Q4. Default branch — options:
main (Recommended) / master
(anything else via Other).
Phase 1b — Flow (second call; Phase 1 is already at the 4-question limit)
- Q5. Integration branch — the branch PRs target and CI gates. Options:
"Same as the default branch: (Recommended)" /
staging
(anything else via Other). It is recorded in CLAUDE.md, not detected.
- Q6. Default flow when several Issues run at once — options:
individual (Recommended — one PR per Issue) / batch (collect them on
epic/<n>-<slug>, verify as a whole, one PR) / stack (each PR targets
the branch of the Issue it depends on). This is only the default: whether
Issues are batched is decided by asking "do these ship together?", never
by the dependency graph.
Phase 2 — Per-language commands
Ask for the primary language in full; for additional languages a quick
confirm of the defaults is enough. Propose these defaults:
| Language |
Install |
Test |
Lint |
Format (hook) |
| Go |
go mod download |
go test ./... |
golangci-lint run (fallback go vet ./...) |
goimports (fallback gofmt) |
| Python (uv) |
uv sync |
uv run pytest |
uv run ruff check |
uv run ruff format |
| Python (pip) |
pip install -e . |
pytest |
ruff check |
ruff format |
| Python (poetry) |
poetry install |
poetry run pytest |
poetry run ruff check |
poetry run ruff format |
| TypeScript |
{pm} install |
{pm} test |
{pm} run lint |
Prettier |
| JavaScript |
{pm} install |
{pm} test |
{pm} run lint |
Prettier |
- Node projects: ask the package manager first (pnpm / npm / yarn / bun;
propose pnpm), then substitute
{pm}.
- TypeScript only: also ask about typecheck (
{pm} exec tsc --noEmit /
a script name / none).
- Python only: ask the package manager (uv / pip / poetry; propose uv).
If uv, ask: "Enable a hook that blocks
pip install in favor of
uv add?" (Y/n).
Phase 3 — Harness scope
Q-H1. Components (multi-select, every entry recommended ON by default):
CLAUDE.md /
format hook / bash-guard hook / SessionStart + Stop guidance hooks /
.claude/rules/ (cycle contract + score-aligned coding principles +
per-language rules for the chosen languages) /
GitHub Actions CI (ci.yml per language + security-scan.yml +
.gitleaks.toml + .semgrepignore; gitleaks and semgrep are hard
gates from day one — shift-left — while trivy starts as informational
continue-on-error) /
.env guard (.gitignore entries + .env.example).
Q-H1b. Optional paid add-on (default OFF; independent of the CI
answer — it composes with a project's existing CI): PR Agent
(.github/workflows/pr-agent.yml + .pr_agent.toml; advisory
qodo-ai/pr-agent review — describe / review / improve when a PR opens,
/review on each push, slash commands for repository members). Needs an
OPENAI_KEY repository secret and API billing; it is advice, never a
required status check.
Q-H1c. How the skills get installed (single choice, propose plugin):
- plugin — the Claude Code plugin. Commands are namespaced
(
/maruda:spec-doc), and the skills always match the setup.sh that
installed the harness. Maps to --plugin (add --plugin-ref <tag> when the
user wants a pinned release rather than main). Say plainly that Claude Code
does not auto-install from settings: --plugin records the marketplace
and marks the plugin enabled, and each person still runs
/plugin install maruda@northraystudio once.
- npx —
npx skills add northraystudio/maruda --skill '*' --agent claude-code -y --copy.
Works with agents other than Claude Code; commands have no namespace
(/spec-doc), so they can collide with other skill collections. Maps to
--with-skills.
- neither — the user installs skills themselves. No flag.
--plugin and --with-skills are two ways to install the same skills, so the
installer rejects them together. If the project already has
.claude/skills/yds-* from an older install, say that those directories are now
stale and should be deleted — the plugin ships the same skills under their new
names, and leaving both registers each skill twice.
Q-H2. Per existing file: merge (append only the missing sections) /
back up then replace / skip.
Q-H3. Bash guard strength: standard (rm -rf /, force-push to the
default branch, redirects into .env) / standard + pip guard (uv
projects) / none.
Phase 4 — Confirm, then apply
Show a summary of every answer and every file that will be created or
modified. Wait for explicit approval. On approval, apply as follows.
Preferred path — run the installer, then refine:
Locate harness/scripts/setup.sh, in this order — the first hit wins:
this skill's own plugin copy, "${CLAUDE_PLUGIN_ROOT}/harness/scripts/setup.sh".
When maruda runs as a plugin, CLAUDE_PLUGIN_ROOT is set in the shell, the
whole repository is in the plugin cache, and the script keeps its executable
bit. Prefer it: the installer is then guaranteed to be the same version as
the skills running the interview. Check with
[[ -n "${CLAUDE_PLUGIN_ROOT:-}" && -f "${CLAUDE_PLUGIN_ROOT}/harness/scripts/setup.sh" ]].
the working repository, if it is maruda or contains a clone/submodule
(harness/scripts/setup.sh, .claude/maruda/harness/scripts/setup.sh).
the network, via the official one-liner. Pin a release tag rather than
main so the installer matches a known version (network required):
curl -fsSL https://raw.githubusercontent.com/northraystudio/maruda/main/harness/scripts/install.sh \
| bash -s -- --langs <langs> --pm <pm> --python-pm <py-pm> --branch <branch> --name <name> \
[--integration-branch <branch>] [--default-flow <individual|batch|stack>] \
[--guard-pip] [--with-skills] [--pr-agent]
Map EVERY Phase 1b / Phase 3 answer to a flag — the applied changes must equal the
approved summary exactly: languages (primary first) → --langs,
Node PM → --pm, Python PM → --python-pm, pip guard → --guard-pip,
integration branch → --integration-branch (omit when it equals the
default branch), default flow → --default-flow,
skill install method → --plugin (+ --plugin-ref) or --with-skills or
neither, CI OFF → --no-ci, format hook OFF →
--no-format-hook, bash guard OFF → --no-bash-guard, guidance hooks
OFF → --no-guidance-hooks, rules OFF → --no-rules, .env guard OFF →
--no-env-guard, PR Agent ON → --pr-agent (allowed with --no-ci,
never with --minimal). If the user wants branch protection applied and gh
is authenticated with admin rights, add --protect.
The installer never overwrites existing files, which is exactly the
merge-safe behavior wanted here.
Then reconcile whatever the installer reported as "kept existing" or
"proposed" against the user's Phase 3 answers:
- The installer never overwrites: files that differ from the incoming
version are written as
<file>.new. For each one, show the user the
diff and offer to merge it (or discard the .new) — apply only what
they approve, then delete the .new file.
- CLAUDE.md kept + user chose merge → append only the missing
sections (Stack & commands for the chosen languages, the cycle
section, Hard rules), following
harness/templates/CLAUDE.md.template.
- settings kept unmerged (no jq) → merge the
hooks block by hand,
preserving every existing user hook.
- Any file the user chose to skip → leave untouched even if the
installer would have created it (delete nothing; just don't add).
Adjust generated CLAUDE.md commands to any non-default answers from
Phase 2 (e.g. a custom test script name).
Fallback (no network, no local copy): report that the harness
templates are unavailable and stop after writing only what can be
written faithfully from this document — do not improvise hook scripts
from memory.
Phase 5 — Verify and report
Print a final checklist:
[maruda harness]
skills: OK (N) / MISSING
CLAUDE.md: CREATED / MERGED / SKIPPED
hooks: OK (selected scripts, executable)
settings: OK / MERGED / needs manual merge
rules: OK / skipped
CI: OK / skipped
flow: integration branch: <branch> | default: <individual|batch|stack>
protection: configured / NOT CONFIGURED / applied
pr-agent: disabled / written (OPENAI_KEY secret required)
next: restart Claude Code to load hooks, then try /maruda:software-evaluation .
Two follow-ups matter for the gates to actually gate:
Branch protection. A CI check only blocks merges once it is a
required status check. The installer reports the state; if it says
NOT CONFIGURED, treat setup as incomplete and either re-run with
--protect (needs gh auth + admin + a pushed default branch) or walk
the user through GitHub settings. Do not report overall success while
protection is unconfigured — report it as an explicit remaining step.
Strict CI. The generated jobs intentionally fail when lint /
typecheck / test scripts (or any tests) are missing. Tell the user the
first code PR must land with those in place — that is the shift-left
contract, not a bug.
PR Agent secret. If --pr-agent was applied, the PR Agent workflow
fails on every PR until the OPENAI_KEY repository secret exists. Report
it as an explicit remaining step; it is advisory and must never be added
to required status checks.
Remind the user that hooks load at session start — a restart (or new
session) is needed before the guard/format hooks take effect.
Stop conditions
- User declines the Phase 4 summary → stop after reporting what would
have changed. Write nothing.
- User declines an overwrite → keep the file, note it in the checklist.
- Unknown/other language requested → set up the supported languages,
leave a
# TODO stack block for the rest, and say so.
Non-goals
- No scheduled loops or cron (L4) — separate task only. Event-driven GitHub
Actions (CI, PR Agent) are in scope.
- No Semgrep / gh installation — mention prerequisites, don't install.
- No rewriting of existing architecture docs or unrelated refactors.
1---2name: setup3description: Install the full maruda harness into the current project through a short interview: CLAUDE.md, hooks, .claude/settings.json, rules, and skill wiring. Asks — never auto-detects — the languages (Go / Python / TypeScript / JavaScript) and commands, then writes files only after an approved summary. Use when the user asks to set up / install / bootstrap maruda, the harness, or the continuous improvement cycle. Triggers: セットアップして, ハーネスを入れて, harnessを入れて, marudaを導入して, プロジェクトを初期化して, '/maruda:setup', 'set up the harness', 'install maruda', 'bootstrap this project'.4---56# maruda Full Harness Setup (Interview Mode)78## Goal910Turn the current repository into a project that runs the11**Diagnose → Register/Draft → Plan → Resolve ⇄ Verify** cycle with12mechanical guardrails (hooks) and a lean CLAUDE.md.1314Skills alone are L1. This setup adds L2–L3: a short project brain15(CLAUDE.md), hard rails (hooks + settings), and cycle guidance (rules).16It never creates scheduled or cron-driven automation (L4); event-driven17GitHub Actions — strict CI and the opt-in PR Agent review — are L2–L3 and18in scope.1920## Principles2122- **Interview, no auto-detection.** Do NOT infer languages from `go.mod`,23 `package.json`, etc., even when they exist. This setup targets24 pre-development projects where detection misleads. File existence is25 used only for overwrite/merge prompts.26- **Never overwrite** existing CLAUDE.md / settings / hooks without27 explicit per-file approval. Prefer merge (append missing sections).28- Hooks enforce hard rules; CLAUDE.md holds soft guidance. Keep29 CLAUDE.md short — detail lives in skills and `.claude/rules/`.30- Write files **only after** the user approves the Phase 4 summary.3132## Workflow3334Ask one phase at a time and wait for answers. If the user says35"use defaults", still require the primary language choice, then apply36the defaults table below to everything else.3738### How to ask (question-tool contract)3940When a structured question tool (e.g. AskUserQuestion) is available, use one41call per phase, and keep every call within the tool's contract — violating it42aborts the turn with "Invalid tool parameters":4344- At most 4 questions per call; **every question needs 2–4 predefined45 options** — never an empty or single-option list. A free-text "Other"46 choice is provided by the tool automatically; rely on it for custom values47 instead of inventing an "enter manually" option list.48- Free-form items (project name, custom commands) must still offer 2+49 options: make option 1 the recommended default (e.g. "Use directory name:50 <dir> (Recommended)") and a sensible alternative; custom values arrive via51 the built-in Other.52- Multi-choice items (additional languages, components) use the tool's53 multi-select mode.54- If the tool is unavailable or returns an error, fall back to asking the55 same questions as plain chat text and wait for the answers — never skip a56 phase because the tool failed.5758### Phase 0 — Preconditions59601. Confirm the target is a git repository (offer `git init` if not).612. Check existence (existence only — do not read to guess the stack) of:62 `CLAUDE.md`, `.claude/settings.json`, `.claude/hooks/`,63 `.claude/rules/maruda-cycle.md`, `.claude/skills/`.643. Tell the user: existing files will each get an overwrite/merge/skip65 question in Phase 3.6667### Phase 1 — Project skeleton (required)6869- **Q1. Project name** — options: "Use directory name: <dir> (Recommended)" /70 "Use repository name" (custom names come via Other).71- **Q2. Primary language (choose exactly one):**72 Go / Python / TypeScript / JavaScript.73- **Q3. Additional languages** (multi-select) — none, or any others from the74 same list.75- **Q4. Default branch** — options: `main` (Recommended) / `master`76 (anything else via Other).7778### Phase 1b — Flow (second call; Phase 1 is already at the 4-question limit)7980- **Q5. Integration branch** — the branch PRs target and CI gates. Options:81 "Same as the default branch: <branch> (Recommended)" / `staging`82 (anything else via Other). It is recorded in CLAUDE.md, not detected.83- **Q6. Default flow when several Issues run at once** — options:84 `individual` (Recommended — one PR per Issue) / `batch` (collect them on85 `epic/<n>-<slug>`, verify as a whole, one PR) / `stack` (each PR targets86 the branch of the Issue it depends on). This is only the default: whether87 Issues are batched is decided by asking "do these ship together?", never88 by the dependency graph.8990### Phase 2 — Per-language commands9192Ask for the primary language in full; for additional languages a quick93confirm of the defaults is enough. Propose these defaults:9495| Language | Install | Test | Lint | Format (hook) |96| --------------- | ------------------ | ------------------- | --------------------------------------------- | ------------------------------ |97| Go | `go mod download` | `go test ./...` | `golangci-lint run` (fallback `go vet ./...`) | `goimports` (fallback `gofmt`) |98| Python (uv) | `uv sync` | `uv run pytest` | `uv run ruff check` | `uv run ruff format` |99| Python (pip) | `pip install -e .` | `pytest` | `ruff check` | `ruff format` |100| Python (poetry) | `poetry install` | `poetry run pytest` | `poetry run ruff check` | `poetry run ruff format` |101| TypeScript | `{pm} install` | `{pm} test` | `{pm} run lint` | Prettier |102| JavaScript | `{pm} install` | `{pm} test` | `{pm} run lint` | Prettier |103104- Node projects: ask the package manager first (pnpm / npm / yarn / bun;105 propose pnpm), then substitute `{pm}`.106- TypeScript only: also ask about typecheck (`{pm} exec tsc --noEmit` /107 a script name / none).108- Python only: ask the package manager (uv / pip / poetry; propose uv).109 If uv, ask: "Enable a hook that blocks `pip install` in favor of110 `uv add`?" (Y/n).111112### Phase 3 — Harness scope113114- **Q-H1. Components** (multi-select, every entry recommended ON by default):115 CLAUDE.md /116 format hook / bash-guard hook / SessionStart + Stop guidance hooks /117 `.claude/rules/` (cycle contract + score-aligned coding principles +118 per-language rules for the chosen languages) /119 GitHub Actions CI (`ci.yml` per language + `security-scan.yml` +120 `.gitleaks.toml` + `.semgrepignore`; gitleaks and semgrep are hard121 gates from day one — shift-left — while trivy starts as informational122 `continue-on-error`) /123 .env guard (`.gitignore` entries + `.env.example`).124- **Q-H1b. Optional paid add-on** (default OFF; independent of the CI125 answer — it composes with a project's existing CI): PR Agent126 (`.github/workflows/pr-agent.yml` + `.pr_agent.toml`; advisory127 qodo-ai/pr-agent review — describe / review / improve when a PR opens,128 `/review` on each push, slash commands for repository members). Needs an129 `OPENAI_KEY` repository secret and API billing; it is advice, never a130 required status check.131- **Q-H1c. How the skills get installed** (single choice, propose *plugin*):132 - **plugin** — the Claude Code plugin. Commands are namespaced133 (`/maruda:spec-doc`), and the skills always match the `setup.sh` that134 installed the harness. Maps to `--plugin` (add `--plugin-ref <tag>` when the135 user wants a pinned release rather than `main`). Say plainly that Claude Code136 does **not** auto-install from settings: `--plugin` records the marketplace137 and marks the plugin enabled, and each person still runs138 `/plugin install maruda@northraystudio` once.139 - **npx** — `npx skills add northraystudio/maruda --skill '*' --agent claude-code -y --copy`.140 Works with agents other than Claude Code; commands have no namespace141 (`/spec-doc`), so they can collide with other skill collections. Maps to142 `--with-skills`.143 - **neither** — the user installs skills themselves. No flag.144145 `--plugin` and `--with-skills` are two ways to install the same skills, so the146 installer rejects them together. If the project already has147 `.claude/skills/yds-*` from an older install, say that those directories are now148 stale and should be deleted — the plugin ships the same skills under their new149 names, and leaving both registers each skill twice.150- **Q-H2. Per existing file**: merge (append only the missing sections) /151 back up then replace / skip.152- **Q-H3. Bash guard strength**: standard (rm -rf /, force-push to the153 default branch, redirects into `.env`) / standard + pip guard (uv154 projects) / none.155156### Phase 4 — Confirm, then apply157158Show a summary of every answer and every file that will be created or159modified. Wait for explicit approval. On approval, apply as follows.160161**Preferred path — run the installer, then refine:**1621631. Locate `harness/scripts/setup.sh`, in this order — the first hit wins:164 - **this skill's own plugin copy**, `"${CLAUDE_PLUGIN_ROOT}/harness/scripts/setup.sh"`.165 When maruda runs as a plugin, `CLAUDE_PLUGIN_ROOT` is set in the shell, the166 whole repository is in the plugin cache, and the script keeps its executable167 bit. Prefer it: the installer is then guaranteed to be the same version as168 the skills running the interview. Check with169 `[[ -n "${CLAUDE_PLUGIN_ROOT:-}" && -f "${CLAUDE_PLUGIN_ROOT}/harness/scripts/setup.sh" ]]`.170 - **the working repository**, if it _is_ maruda or contains a clone/submodule171 (`harness/scripts/setup.sh`, `.claude/maruda/harness/scripts/setup.sh`).172 - **the network**, via the official one-liner. Pin a release tag rather than173 `main` so the installer matches a known version (network required):174175 ```bash176 curl -fsSL https://raw.githubusercontent.com/northraystudio/maruda/main/harness/scripts/install.sh \177 | bash -s -- --langs <langs> --pm <pm> --python-pm <py-pm> --branch <branch> --name <name> \178 [--integration-branch <branch>] [--default-flow <individual|batch|stack>] \179 [--guard-pip] [--with-skills] [--pr-agent]180 ```181182 Map EVERY Phase 1b / Phase 3 answer to a flag — the applied changes must equal the183 approved summary exactly: languages (primary first) → `--langs`,184 Node PM → `--pm`, Python PM → `--python-pm`, pip guard → `--guard-pip`,185 integration branch → `--integration-branch` (omit when it equals the186 default branch), default flow → `--default-flow`,187 skill install method → `--plugin` (+ `--plugin-ref`) or `--with-skills` or188 neither, CI OFF → `--no-ci`, format hook OFF →189 `--no-format-hook`, bash guard OFF → `--no-bash-guard`, guidance hooks190 OFF → `--no-guidance-hooks`, rules OFF → `--no-rules`, .env guard OFF →191 `--no-env-guard`, PR Agent ON → `--pr-agent` (allowed with `--no-ci`,192 never with `--minimal`). If the user wants branch protection applied and `gh`193 is authenticated with admin rights, add `--protect`.194 The installer never overwrites existing files, which is exactly the195 merge-safe behavior wanted here.1961972. Then reconcile whatever the installer reported as "kept existing" or198 "proposed" against the user's Phase 3 answers:199 - The installer never overwrites: files that differ from the incoming200 version are written as `<file>.new`. For each one, show the user the201 diff and offer to merge it (or discard the `.new`) — apply only what202 they approve, then delete the `.new` file.203 - CLAUDE.md kept + user chose **merge** → append only the missing204 sections (Stack & commands for the chosen languages, the cycle205 section, Hard rules), following `harness/templates/CLAUDE.md.template`.206 - settings kept unmerged (no jq) → merge the `hooks` block by hand,207 preserving every existing user hook.208 - Any file the user chose to **skip** → leave untouched even if the209 installer would have created it (delete nothing; just don't add).2103. Adjust generated CLAUDE.md commands to any non-default answers from211 Phase 2 (e.g. a custom test script name).212213**Fallback (no network, no local copy):** report that the harness214templates are unavailable and stop after writing only what can be215written faithfully from this document — do not improvise hook scripts216from memory.217218### Phase 5 — Verify and report219220Print a final checklist:221222```223[maruda harness]224 skills: OK (N) / MISSING225 CLAUDE.md: CREATED / MERGED / SKIPPED226 hooks: OK (selected scripts, executable)227 settings: OK / MERGED / needs manual merge228 rules: OK / skipped229 CI: OK / skipped230 flow: integration branch: <branch> | default: <individual|batch|stack>231 protection: configured / NOT CONFIGURED / applied232 pr-agent: disabled / written (OPENAI_KEY secret required)233 next: restart Claude Code to load hooks, then try /maruda:software-evaluation .234```235236Two follow-ups matter for the gates to actually gate:237238- **Branch protection.** A CI check only blocks merges once it is a239 required status check. The installer reports the state; if it says240 NOT CONFIGURED, treat setup as incomplete and either re-run with241 `--protect` (needs `gh` auth + admin + a pushed default branch) or walk242 the user through GitHub settings. Do not report overall success while243 protection is unconfigured — report it as an explicit remaining step.244- **Strict CI.** The generated jobs intentionally fail when lint /245 typecheck / test scripts (or any tests) are missing. Tell the user the246 first code PR must land with those in place — that is the shift-left247 contract, not a bug.248249- **PR Agent secret.** If `--pr-agent` was applied, the `PR Agent` workflow250 fails on every PR until the `OPENAI_KEY` repository secret exists. Report251 it as an explicit remaining step; it is advisory and must never be added252 to required status checks.253254Remind the user that hooks load at session start — a restart (or new255session) is needed before the guard/format hooks take effect.256257## Stop conditions258259- User declines the Phase 4 summary → stop after reporting what _would_260 have changed. Write nothing.261- User declines an overwrite → keep the file, note it in the checklist.262- Unknown/other language requested → set up the supported languages,263 leave a `# TODO` stack block for the rest, and say so.264265## Non-goals266267- No scheduled loops or cron (L4) — separate task only. Event-driven GitHub268 Actions (CI, PR Agent) are in scope.269- No Semgrep / gh installation — mention prerequisites, don't install.270- No rewriting of existing architecture docs or unrelated refactors.