Skip to content

Commit f3c4209

Browse files
Merge pull request #2 from RedHatInsights/update-instructions
Add dynamic persona selection
2 parents e33557d + d35f5be commit f3c4209

6 files changed

Lines changed: 134 additions & 62 deletions

File tree

ARCHITECTURE.md

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ The actual intelligence. Claude Code is spawned as a subprocess by the Agent SDK
8989
- **Prompt**: `"Your primary label is: <label>. Follow the instructions in CLAUDE.md."`
9090
- **CLAUDE.md**: detailed behavioral instructions covering the full workflow (priority system, PR maintenance, ticket claiming, implementation guidelines, memory usage, progress tracking)
9191
- **Tools**: Built-in (Read, Write, Edit, Bash, Grep, Glob, LSP) + MCP tools (Jira, memory, browser)
92-
- **Persona prompts**: Loaded from `personas/<type>/prompt.md` based on which repo it's working in
92+
- **Persona prompts**: Loaded from `personas/<type>/prompt.md` based on the ticket's nature and repo tech stack
9393

9494
The agent has no persistent state between cycles. All state is stored in the memory server (task records) and reconstructed at the start of each cycle.
9595

@@ -132,16 +132,17 @@ Runs as two Docker containers:
132132

133133
Domain-specific guidelines that tell the agent how to work in different types of repos. Each persona is a markdown file with coding standards, testing commands, and conventions.
134134

135-
| Persona | Repos | Key Details |
136-
|---------|-------|-------------|
135+
| Persona | Applies to | Key Details |
136+
|---------|------------|-------------|
137137
| `frontend` | React/TS/PatternFly apps | `npm run lint/test`, visual verification via browser MCP, PatternFly component MCP |
138138
| `backend` | Go and Node.js services | `make test` / `npm test`, Go conventions |
139139
| `rbac` | insights-rbac (Django/DRF) | Docker Compose dev env, `make unittest-fast`, PostgreSQL + Redis + Celery |
140140
| `operator` | Kubernetes operators | Go, controller-runtime patterns |
141-
| `config` | app-interface | GitLab fork workflow, read-only or MR-based |
142-
| `cve` | CVE remediation | Dependency upgrades, grype scanning |
141+
| `config` | Config/YAML repos (e.g. app-interface) | GitLab fork workflow, read-only or MR-based |
142+
| `cve` | CVE remediation (any repo) | Dependency upgrades, base image updates, grype scanning |
143+
| `tooling` | Build/dev infrastructure | Dockerfiles, shell scripts, proxy configs |
143144

144-
A repo can have multiple personas (e.g. `["frontend", "cve"]`). The agent picks the best fit based on the ticket description.
145+
Personas are NOT hardcoded to repos. The bot dynamically selects the best-fit persona(s) based on the ticket description and the repo's tech stack (e.g. `package.json`frontend, `go.mod` → backend/operator, Dockerfile-only → tooling). CVE persona layers on top of the base persona.
145146

146147
### Target Repos (`repos/`)
147148

@@ -150,13 +151,11 @@ Cloned on demand when the bot picks up a ticket. Repo metadata is in `project-re
150151
```json
151152
{
152153
"notifications-frontend": {
153-
"url": "git@github.com:RedHatInsights/notifications-frontend.git",
154-
"personas": ["frontend", "cve"]
154+
"url": "git@github.com:RedHatInsights/notifications-frontend.git"
155155
},
156156
"app-interface": {
157157
"url": "git@gitlab.cee.redhat.com:yourfork/app-interface.git",
158158
"upstream": "git@gitlab.cee.redhat.com:service/app-interface.git",
159-
"personas": ["config"],
160159
"host": "gitlab"
161160
}
162161
}
@@ -165,7 +164,6 @@ Cloned on demand when the bot picks up a ticket. Repo metadata is in `project-re
165164
Fields:
166165
- `url` — git clone URL (may be a fork)
167166
- `upstream` — (optional) original repo URL. Bot syncs from upstream, pushes to fork, opens MRs against upstream
168-
- `personas` — applicable persona types
169167
- `host``"gitlab"` for GitLab repos (default: GitHub)
170168
- `readonly` — if `true`, bot reads only, never pushes
171169

CLAUDE.md

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,6 @@ Before starting work on a ticket, use `jira_get_issue` to read the full ticket i
266266
5. **Prepare the repos**: Collect all `repo:` labels from the ticket. For each one, match it to `project-repos.json` to find the repo config. Each repo has:
267267
- `url` — the git clone URL (may be a fork — see `upstream` below)
268268
- `upstream` (optional) — the upstream repo URL. When present, `url` is a **fork** and `upstream` is the original repo. The bot clones from `url`, syncs from `upstream`, and opens MRs targeting the upstream repo.
269-
- `personas` — array of applicable persona types (e.g. `["frontend", "cve"]`). A repo can have multiple personas — pick the one most relevant to the ticket at hand.
270269
- `host` (optional) — `"gitlab"` for GitLab repos. If absent, the repo is on GitHub.
271270
- `readonly` (optional) — if `true`, do not push or open PRs in this repo, only read it for context
272271

@@ -304,15 +303,28 @@ Before starting work on a ticket, use `jira_get_issue` to read the full ticket i
304303

305304
**Read repo-level instructions**: After entering each repo, check if it contains a `CLAUDE.md` file at its root. If it does, read it in full. If that file references other instruction files (e.g. `@AGENTS.md`), read those too. These contain critical repo-specific architectural guidance, coding standards, and constraints. Follow them alongside the persona guidelines. **When repo-level instructions conflict with persona guidelines, the repo-level instructions take precedence** — they are written by the repo maintainers and reflect the ground truth for that codebase.
306305

307-
6. **Load personas**: Each repo in `project-repos.json` has a `personas` array listing all applicable persona types. For the ticket at hand:
308-
309-
- **Select the best-fit persona** for each repo based on the ticket description. For example, if a repo has `["frontend", "cve"]` and the ticket is about a CVE fix, use the `cve` persona. If it's about a UI change, use `frontend`. If unclear, load all and apply the most relevant guidelines.
310-
- For each selected persona, read `personas/<persona>/prompt.md`.
311-
- If a ticket spans multiple repos with different personas, load ALL relevant persona prompts upfront.
312-
313-
**Persona scoping**: Each persona's guidelines apply ONLY when working in repos where that persona was selected. For example:
314-
- Frontend persona rules (PatternFly, visual verification, `npm run lint`) apply when using the `frontend` persona.
315-
- Backend persona rules apply when using the `backend` persona.
306+
6. **Load personas**: Personas are NOT hardcoded to repos. Instead, select the right persona(s) dynamically based on the ticket and the repo's tech stack.
307+
308+
**How to pick personas:**
309+
1. List available personas by scanning the `personas/` directory for subdirectories containing `prompt.md`.
310+
2. Inspect each repo to determine its tech stack:
311+
- Has `package.json` with React/PatternFly dependencies → likely needs `frontend`
312+
- Has `go.mod` → likely needs `backend` (Go) or `operator` (if it's a K8s operator)
313+
- Has `Pipfile` or `requirements.txt` with Django → likely needs `backend` or a repo-specific persona (e.g. `rbac`)
314+
- Has only Dockerfiles, shell scripts, Caddyfiles → likely needs `tooling`
315+
- Is a config/YAML repo (e.g. app-interface) → likely needs `config`
316+
3. Consider the ticket's nature:
317+
- CVE/security vulnerability ticket → also load `cve` persona (applies on top of the repo's base persona)
318+
- RBAC-specific ticket for insights-rbac → load `rbac` persona
319+
- Ticket about K8s operator CRDs/controllers → load `operator` persona
320+
4. Read `personas/<persona>/prompt.md` for each selected persona.
321+
5. If a ticket spans multiple repos with different tech stacks, load ALL relevant personas upfront.
322+
323+
**Persona scoping**: Each persona's guidelines apply ONLY when working in repos where that persona is relevant. For example:
324+
- Frontend persona rules (PatternFly, visual verification, `npm run lint`) apply only in React/frontend repos.
325+
- Backend persona rules apply only in Go/Node.js service repos.
326+
- Tooling persona rules apply only in build/infra repos with Dockerfiles and scripts.
327+
- CVE persona guidelines layer on top of the base persona — they don't replace it.
316328
- Do NOT apply frontend-specific rules (e.g. visual verification) to backend work, or vice versa.
317329

318330
**Cross-repo coordination**: When a ticket requires changes across multiple repos, plan the work holistically before starting:

README.md

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,7 @@ The bot is a good developer but has zero tribal knowledge. Don't assume it knows
138138
1. Add to `project-repos.json`:
139139
```json
140140
"my-repo": {
141-
"url": "git@github.com:RedHatInsights/my-repo.git",
142-
"personas": ["frontend"]
141+
"url": "git@github.com:RedHatInsights/my-repo.git"
143142
}
144143
```
145144
2. Add a `repo:my-repo` label to the Jira ticket
@@ -154,25 +153,15 @@ If the bot doesn't have push access to the upstream repo, use a fork:
154153
"app-interface": {
155154
"url": "git@gitlab.cee.redhat.com:youruser/app-interface.git",
156155
"upstream": "git@gitlab.cee.redhat.com:service/app-interface.git",
157-
"personas": ["config"],
158156
"host": "gitlab"
159157
}
160158
```
161159

162160
The bot clones from the fork, syncs from upstream, pushes branches to the fork, and opens MRs targeting the upstream repo.
163161

164-
### Multi-persona repos
162+
### Persona selection
165163

166-
A repo can support multiple personas. The bot selects the best fit based on the ticket:
167-
168-
```json
169-
"insights-rbac": {
170-
"url": "git@github.com:RedHatInsights/insights-rbac.git",
171-
"personas": ["backend", "rbac"]
172-
}
173-
```
174-
175-
If a ticket is about RBAC-specific Django work, the bot loads the `rbac` persona. For generic backend work, it uses `backend`.
164+
Personas are NOT hardcoded to repos. The bot dynamically selects the best-fit persona(s) based on the ticket description and the repo's tech stack (e.g. `package.json``frontend`, `go.mod``backend`/`operator`, Dockerfile-only → `tooling`, config repo → `config`). For CVE tickets, the `cve` persona layers on top of the base persona.
176165

177166
## Running the services
178167

@@ -262,7 +251,8 @@ Each repo has one or more personas that provide domain-specific guidelines. Pers
262251
| `rbac` | Django/DRF RBAC service (insights-rbac). Docker Compose dev env, `make unittest-fast`. |
263252
| `operator` | Kubernetes operators (Go). |
264253
| `config` | Config repos (app-interface). Read-only or GitLab MR workflow. |
265-
| `cve` | CVE remediation — dependency upgrades and security scanning. |
254+
| `cve` | CVE remediation — dependency upgrades, base image updates, security scanning. |
255+
| `tooling` | Build/dev infrastructure — Dockerfiles, shell scripts, proxy configs. |
266256

267257
## Memory system
268258

bot/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ def sanitize_env() -> None:
113113
"mcp__mcp-atlassian__jira_get_sprints_from_board",
114114
"mcp__mcp-atlassian__jira_add_issues_to_sprint",
115115
"mcp__mcp-atlassian__jira_create_issue",
116+
"mcp__mcp-atlassian__jira_create_issue_link",
116117
"mcp__mcp-atlassian__jira_get_field_options",
117118
# Wildcard MCP tools
118119
"mcp__hcc-patternfly-data-view__*",

personas/tooling/prompt.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
## Tooling & Build Infrastructure Guidelines
2+
3+
You are working on a build/dev tooling repo — Dockerfiles, shell scripts, proxy configs, CI pipelines, and similar infrastructure that supports frontend and backend applications.
4+
5+
### General
6+
7+
- These repos are NOT application code. They are shared infrastructure used by many teams.
8+
- Changes here have a wide blast radius — a broken build image or proxy affects all frontend apps.
9+
- Follow existing patterns. These repos prioritize stability over cleverness.
10+
- Read the repo's `README.md` and any docs for repo-specific conventions.
11+
12+
### Dockerfiles
13+
14+
- Use multi-stage builds where appropriate.
15+
- Prefer UBI (Universal Base Image) base images for production.
16+
- Keep images minimal — only install what's needed.
17+
- Never hardcode secrets or tokens in Dockerfiles. Use build args or mounted secrets.
18+
- Pin base image versions to specific tags, not `latest`.
19+
- Run as non-root user where possible.
20+
21+
### Shell scripts
22+
23+
- Use `set -euo pipefail` at the top of scripts.
24+
- Quote all variables: `"${VAR}"` not `$VAR`.
25+
- Use `shellcheck` if available to lint scripts.
26+
- Add comments explaining non-obvious logic — these scripts are maintained by many people.
27+
- Test scripts locally before committing.
28+
29+
### Proxy / Caddy / NGINX configs
30+
31+
- Test config changes against a real running instance if possible.
32+
- Be careful with route ordering — more specific routes before catch-alls.
33+
- Document any new environment variables or config options.
34+
35+
### Go plugins (e.g. Caddy modules)
36+
37+
- Follow Go conventions: `go vet`, `gofmt`, table-driven tests.
38+
- Use `go build` to verify compilation.
39+
- Run `go test ./...` for any Go code.
40+
41+
### Testing
42+
43+
- For shell scripts: test edge cases (missing files, empty vars, special characters).
44+
- For Dockerfiles: build the image and verify it starts correctly.
45+
- For config changes: validate syntax before committing.
46+
- Run any existing test suites: check for `test/`, `Makefile` targets, or CI scripts.
47+
48+
### CVE fixes in these repos
49+
50+
- CVEs here are typically in base images or system packages, not application dependencies.
51+
- Fix by updating the base image tag or adding explicit `dnf update` / `apk upgrade` for affected packages.
52+
- Verify the CVE is actually resolved in the new image by checking package versions.

project-repos.json

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,79 @@
11
{
22
"insights-chrome": {
3-
"url": "git@github.com:RedHatInsights/insights-chrome.git",
4-
"personas": ["frontend", "cve"]
3+
"url": "git@github.com:RedHatInsights/insights-chrome.git"
54
},
65
"astro-virtual-assistant-frontend": {
7-
"url": "git@github.com:RedHatInsights/astro-virtual-assistant-frontend.git",
8-
"personas": ["frontend"]
6+
"url": "git@github.com:RedHatInsights/astro-virtual-assistant-frontend.git"
97
},
108
"widget-layout": {
11-
"url": "git@github.com:RedHatInsights/widget-layout.git",
12-
"personas": ["frontend"]
9+
"url": "git@github.com:RedHatInsights/widget-layout.git"
1310
},
1411
"widget-layout-backend": {
15-
"url": "git@github.com:RedHatInsights/widget-layout-backend.git",
16-
"personas": ["backend"]
12+
"url": "git@github.com:RedHatInsights/widget-layout-backend.git"
1713
},
1814
"notifications-frontend": {
19-
"url": "git@github.com:RedHatInsights/notifications-frontend.git",
20-
"personas": ["frontend", "cve"]
15+
"url": "git@github.com:RedHatInsights/notifications-frontend.git"
2116
},
2217
"frontend-operator": {
23-
"url": "git@github.com:RedHatInsights/frontend-operator.git",
24-
"personas": ["operator"]
18+
"url": "git@github.com:RedHatInsights/frontend-operator.git"
2519
},
2620
"app-interface": {
2721
"url": "git@gitlab.cee.redhat.com:mmarosi/app-interface.git",
2822
"upstream": "git@gitlab.cee.redhat.com:service/app-interface.git",
29-
"personas": ["config"],
3023
"host": "gitlab"
3124
},
3225
"quickstarts": {
33-
"url": "git@github.com:RedHatInsights/quickstarts.git",
34-
"personas": ["backend"]
26+
"url": "git@github.com:RedHatInsights/quickstarts.git"
3527
},
3628
"learning-resources": {
37-
"url": "git@github.com:RedHatInsights/learning-resources.git",
38-
"personas": ["frontend"]
29+
"url": "git@github.com:RedHatInsights/learning-resources.git"
3930
},
4031
"payload-tracker-frontend": {
41-
"url": "git@github.com:RedHatInsights/payload-tracker-frontend.git",
42-
"personas": ["frontend", "cve"]
32+
"url": "git@github.com:RedHatInsights/payload-tracker-frontend.git"
4333
},
4434
"pdf-generator": {
45-
"url": "git@github.com:RedHatInsights/pdf-generator.git",
46-
"personas": ["backend", "cve"]
35+
"url": "git@github.com:RedHatInsights/pdf-generator.git"
4736
},
4837
"chrome-service-backend": {
49-
"url": "git@github.com:RedHatInsights/chrome-service-backend.git",
50-
"personas": ["backend"]
38+
"url": "git@github.com:RedHatInsights/chrome-service-backend.git"
5139
},
5240
"astro-virtual-assistant-v2": {
53-
"url": "git@github.com:RedHatInsights/astro-virtual-assistant-v2.git",
54-
"personas": ["backend"]
41+
"url": "git@github.com:RedHatInsights/astro-virtual-assistant-v2.git"
5542
},
5643
"insights-rbac": {
57-
"url": "git@github.com:RedHatInsights/insights-rbac.git",
58-
"personas": ["backend", "rbac"]
44+
"url": "git@github.com:RedHatInsights/insights-rbac.git"
45+
},
46+
"javascript-clients": {
47+
"url": "git@github.com:RedHatInsights/javascript-clients.git"
48+
},
49+
"frontend-components": {
50+
"url": "git@github.com:RedHatInsights/frontend-components.git"
51+
},
52+
"patchman-ui": {
53+
"url": "git@github.com:RedHatInsights/patchman-ui.git"
54+
},
55+
"insights-advisor-frontend": {
56+
"url": "git@github.com:RedHatInsights/insights-advisor-frontend.git"
57+
},
58+
"ocp-advisor-frontend": {
59+
"url": "git@github.com:RedHatInsights/ocp-advisor-frontend.git"
60+
},
61+
"insights-remediations-frontend": {
62+
"url": "git@github.com:RedHatInsights/insights-remediations-frontend.git"
63+
},
64+
"insights-inventory-frontend": {
65+
"url": "git@github.com:RedHatInsights/insights-inventory-frontend.git"
66+
},
67+
"malware-detection-frontend": {
68+
"url": "git@github.com:RedHatInsights/malware-detection-frontend.git"
69+
},
70+
"vuln4shift-frontend": {
71+
"url": "git@github.com:RedHatInsights/vuln4shift-frontend.git"
72+
},
73+
"insights-frontend-builder-common": {
74+
"url": "git@github.com:RedHatInsights/insights-frontend-builder-common.git"
75+
},
76+
"frontend-development-proxy": {
77+
"url": "git@github.com:RedHatInsights/frontend-development-proxy.git"
5978
}
6079
}

0 commit comments

Comments
 (0)