Skip to content

Commit 03a00ac

Browse files
Ambient Code Botclaude
andcommitted
fix: address CodeRabbit review comments — add grep patterns, fix docs, improve evals
- operator-review: replace fragile grep with rg -U for multi-line O1 check; add concrete grep/rg detection patterns for O2 and O6 - security-review: add executable bash detection patterns for S1–S6 so automated agents can produce pass/fail signals - cypress-demo: fix incomplete curl URL (add :3000 port); clarify helpers must be embedded in each demo file (not in sessions.cy.ts); qualify 'complete working example' claim about sessions.cy.ts - pr-fixer: document that gh pr view returns uppercase state (OPEN/CLOSED/MERGED) and that non-existent PRs produce non-zero exit + stderr (not JSON) - pr-fixer/evals: add URL-form and punctuation-trailing PR number fixtures - scaffold/evals: include integration target in expected_args for natural- language PagerDuty case so routing failures don't silently pass - unleash-flag: replace unsafe inline token export with non-echoing read prompt guidance; add note to log len(token) not the value itself - jira.log.md: add issue_type normalization note (Story|Bug|Task allowlist, normalize case, reject unrecognized values) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent c5c4c34 commit 03a00ac

File tree

8 files changed

+109
-15
lines changed

8 files changed

+109
-15
lines changed

.claude/agents/operator-review.md

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,29 @@ Load these files before running checks:
2828
### O1: OwnerReferences on child resources (Blocker)
2929

3030
```bash
31-
grep -rn "Jobs\?\|Secrets\?\|PersistentVolumeClaims\?" components/operator/ --include="*.go" | grep -i "create"
31+
# Find client.Create calls (handles multi-line builder chains)
32+
rg -U "\.Create\s*\(" components/operator/ --glob="*.go" -l
33+
# Then for each file, check whether OwnerReferences is set before Create
34+
rg "OwnerReferences|controllerutil\.SetControllerReference" components/operator/ --glob="*.go"
3235
```
3336

34-
Cross-reference each create call with `OwnerReferences` in the same function. See `DEVELOPMENT.md` for the required pattern.
37+
For each `Create(` call in `components/operator/`, verify the created object's `metadata.OwnerReferences` is populated (or `controllerutil.SetControllerReference` is called) in the same function. See `DEVELOPMENT.md` for the required pattern.
3538

3639
### O2: Proper reconciliation patterns (Critical)
3740

3841
- `errors.IsNotFound` → return nil (resource deleted, don't retry)
3942
- Transient errors → return error (triggers requeue with backoff)
4043
- Terminal errors → update CR status to "Failed", return nil
4144

45+
```bash
46+
# Find IsNotFound usages — verify they return nil, not an error
47+
rg -n "errors\.IsNotFound" components/operator/ --glob="*.go" -A 2
48+
# Find status updates that set Failed but still return errors (bad pattern: should return nil)
49+
rg -U "status.*Failed|Failed.*status" components/operator/ --glob="*.go" -A 3
50+
# Find Reconcile/reconcile functions for manual review of error return paths
51+
rg -n "^func.*[Rr]econcile" components/operator/ --glob="*.go"
52+
```
53+
4254
### O3: SecurityContext on Job pod specs (Critical)
4355

4456
```bash
@@ -65,6 +77,15 @@ grep -rn "panic(" components/operator/ --include="*.go" | grep -v "_test.go"
6577

6678
Error paths must update the CR status to reflect the error.
6779

80+
```bash
81+
# Find status update calls
82+
rg -n "status\.Update|Status\.Conditions|SetCondition|UpdateStatus" components/operator/ --glob="*.go" | grep -v "_test.go"
83+
# Find error returns in Reconcile functions without preceding status update (flag for manual review)
84+
rg -n "return.*ctrl\.Result|return.*err" components/operator/ --glob="*.go" | grep -v "_test.go"
85+
```
86+
87+
For each error return path in `Reconcile`, verify a status update (setting condition to `Failed` or similar) occurs before returning.
88+
6889
### O7: No context.TODO() (Minor)
6990

7091
```bash

.claude/agents/security-review.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,26 +27,70 @@ Load these files before running checks:
2727

2828
Handlers must use `GetK8sClientsForRequest(c)` for user-initiated operations. Service account only for privileged operations after RBAC validation.
2929

30+
```bash
31+
# Find handler functions using service account clients without RBAC validation
32+
rg -n "GetK8sClientsForRequest|serviceAccountClient|saClient" components/ --glob="*.go" | grep -v "_test.go"
33+
# Flag handlers that don't call GetK8sClientsForRequest (manual review for user-flow endpoints)
34+
rg -n "func.*Handler\|func.*Handle" components/backend/ --glob="*.go" -A 5 | grep -v "GetK8sClientsForRequest" | grep "func.*Handler"
35+
```
36+
3037
### S2: RBAC before resource access (Critical)
3138

3239
`SelfSubjectAccessReview` (or equivalent authz check) should precede user-scoped resource access.
3340

41+
```bash
42+
# Find SelfSubjectAccessReview usage — flag user-resource endpoints that lack it
43+
rg -n "SelfSubjectAccessReview|SubjectAccessReview" components/ --glob="*.go" | grep -v "_test.go"
44+
# Find resource access patterns without preceding RBAC check (flag for manual review)
45+
rg -n "client\.Get\|client\.List\|client\.Create" components/backend/ --glob="*.go" -B 10 | grep -v "SelfSubjectAccessReview"
46+
```
47+
3448
### S3: Token redaction in all outputs (Blocker)
3549

3650
No tokens in logs, errors, or API responses. Use `len(token)` for logging.
3751

52+
```bash
53+
# Find token variables logged directly (should use len(token) instead)
54+
rg -n "log.*[Tt]oken\|Sprintf.*[Tt]oken\|Error.*[Tt]oken" components/ --glob="*.go" | grep -v "_test.go" | grep -v "len(token)"
55+
# Find token values in response bodies
56+
rg -n '"token"\s*:\s*[a-zA-Z]' components/ --glob="*.go" | grep -v "_test.go"
57+
```
58+
3859
### S4: Input validation (Major)
3960

4061
DNS labels validated, URLs parsed, no raw newlines for log injection.
4162

63+
```bash
64+
# Find URL construction without url.Parse validation
65+
rg -n "url\.Parse\|url\.ParseRequestURI" components/ --glob="*.go" | grep -v "_test.go"
66+
# Find log statements with user-controlled input (potential log injection via newlines)
67+
rg -n 'log\.(Info|Error|Warn).*(name|label|input|param|query)' components/ --glob="*.go" | grep -v "_test.go"
68+
# Find DNS label handling without regex validation
69+
rg -n "IsDNSLabel\|dns1123\|ValidateName" components/ --glob="*.go" | grep -v "_test.go"
70+
```
71+
4272
### S5: SecurityContext on pods (Critical)
4373

4474
`AllowPrivilegeEscalation: false`, `Capabilities.Drop: ["ALL"]`.
4575

76+
```bash
77+
# Find PodSpec/container definitions — verify SecurityContext is set
78+
rg -n "AllowPrivilegeEscalation\|Capabilities" components/ --glob="*.go" | grep -v "_test.go"
79+
# Flag pod/container specs missing AllowPrivilegeEscalation
80+
rg -U "corev1\.Container\{[^}]*\}" components/ --glob="*.go" --multiline | grep -v "AllowPrivilegeEscalation"
81+
```
82+
4683
### S6: OwnerReferences on Secrets (Critical)
4784

4885
Secrets created by the platform must have OwnerReferences for cleanup.
4986

87+
```bash
88+
# Find Secret create calls
89+
rg -n "corev1\.Secret\|&v1\.Secret\|Secrets\(\)" components/ --glob="*.go" | grep -v "_test.go"
90+
# Find Secret creation sites — verify OwnerReferences is set
91+
rg -n "client\.Create.*[Ss]ecret\|Create.*corev1\.Secret" components/ --glob="*.go" -B 10 | grep -v "_test.go" | grep -v "OwnerReferences"
92+
```
93+
5094
### S7: No hardcoded credentials (Blocker)
5195

5296
```bash

.claude/commands/jira.log.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Extract the following from `$ARGUMENTS`:
2222

2323
- **Summary** (required): The title/summary of the issue
2424
- **Description** (optional): Detailed description of the work
25-
- **Issue Type** (optional): Defaults to `Story`, but can be `Bug` or `Task`. Tasks are tech debt related and not user facing
25+
- **Issue Type** (optional): Defaults to `Story`, but can be `Bug` or `Task`. Tasks are tech debt related and not user facing. Normalize case before use (e.g. "bug" → "Bug", "TASK" → "Task") and validate against this allowlist; reject unrecognized values with a prompt to the user.
2626
- **Priority** (optional): Defaults to `Normal`
2727

2828
If the user provides a simple sentence, use it as the summary. If they provide multiple lines, use the first line as summary and the rest as description.
@@ -119,7 +119,7 @@ Use the `mcp__jira__jira_create_issue` tool with:
119119
{
120120
"project_key": "RHOAIENG",
121121
"summary": "[user provided summary]",
122-
"issue_type": "[parsed issue type from step 1]",
122+
"issue_type": "[validated issue type: normalize to Story|Bug|Task — default Story if unrecognized]",
123123
"description": "[structured description from template]",
124124
"components": "Agentic",
125125
"additional_fields": "{\"labels\": [\"team:ambient\"]}"

.claude/skills/cypress-demo/SKILL.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,20 @@ When invoked, create a Cypress test file in `e2e/cypress/e2e/` that records a de
4747
- Verify `e2e/.env.test` or `e2e/.env` exists with `TEST_TOKEN`
4848
- Check if `ANTHROPIC_API_KEY` is available (needed for Running state)
4949
- Verify the kind cluster is up: `kubectl get pods -n ambient-code`
50-
- Verify the frontend is accessible: `curl -s -o /dev/null -w "%{http_code}" http://localhost`
50+
- Verify the frontend is accessible: `curl -s -o /dev/null -w "%{http_code}" http://localhost:3000`
5151

5252
### 3. Create the demo test file
5353

5454
Create `e2e/cypress/e2e/<feature-name>-demo.cy.ts` using the helpers below.
5555

5656
#### Required helpers
5757

58-
Copy the demo helpers (cursor, caption, click ripple, timing constants) from the reference implementation at `e2e/cypress/e2e/sessions.cy.ts` into each new demo file. The helpers are: `caption()`, `clearCaption()`, `initCursor()`, `moveTo()`, `moveToText()`, `clickEffect()`, `cursorClickText()`, plus timing constants (`LONG`, `PAUSE`, `SHORT`, `TYPE_DELAY`).
58+
Each demo file must define the following helpers inline (they are not shared utilities — embed them directly in the test file):
59+
60+
- **Functions**: `caption()`, `clearCaption()`, `initCursor()`, `moveTo()`, `moveToText()`, `clickEffect()`, `cursorClickText()`
61+
- **Timing constants**: `LONG`, `PAUSE`, `SHORT`, `TYPE_DELAY`
62+
63+
See the patterns table below for usage. If a prior demo file already exists in `e2e/cypress/e2e/`, copy the helpers from there; otherwise implement them fresh using the patterns below.
5964

6065
### 4. Key patterns
6166

@@ -77,4 +82,4 @@ npx cypress run --no-runner-ui --spec "cypress/e2e/<name>-demo.cy.ts"
7782

7883
### 6. Reference implementation
7984

80-
See `e2e/cypress/e2e/sessions.cy.ts` for a complete working example.
85+
`e2e/cypress/e2e/sessions.cy.ts` is a reference for test structure and Cypress patterns in this repo. Note that sessions.cy.ts is a functional test, not a demo test — it does not contain the cursor/caption/click-ripple helpers listed above. Use it as a guide for selectors, workspace setup, and polling patterns; implement the demo-specific helpers fresh in your new file.

.claude/skills/pr-fixer/SKILL.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,14 @@ The PR number is required. Example: `/pr-fixer 1234`
2525
- Confirm the repo has a `pr-fixer.yml` workflow
2626

2727
2. **Pre-flight PR check**
28-
- Verify the PR exists and is open: `gh pr view <N> --repo <owner/repo> --json state --jq .state`
29-
- If PR is closed/merged, abort with: "PR #N is already <state>. Nothing to fix."
30-
- If PR doesn't exist, abort with: "PR #N not found in <owner/repo>."
28+
- Check the PR exists and its state:
29+
```bash
30+
gh pr view <N> --repo <owner/repo> --json state --jq .state
31+
```
32+
- `gh pr view` returns state in **uppercase**: `OPEN`, `CLOSED`, or `MERGED`. A non-zero exit code (with stderr error) means the PR does not exist.
33+
- If the exit code is non-zero: abort with "PR #N not found in <owner/repo>."
34+
- If state is `CLOSED` or `MERGED`: abort with "PR #N is already <state>. Nothing to fix." (use the actual uppercase value returned)
35+
- Only proceed if state is exactly `OPEN`.
3136

3237
3. **Dispatch the workflow**
3338
```bash

.claude/skills/pr-fixer/evals/evals.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,18 @@
1717
"expected_args": { "skill": "pr-fixer", "args": "987" },
1818
"description": "Natural language with hash prefix on PR number"
1919
},
20+
{
21+
"input": "fix https://github.com/org/repo/pull/1234",
22+
"expected_tool_call": "Skill",
23+
"expected_args": { "skill": "pr-fixer", "args": "1234" },
24+
"description": "URL-form PR reference — extracts PR number from full GitHub URL"
25+
},
26+
{
27+
"input": "please fix PR 1234.",
28+
"expected_tool_call": "Skill",
29+
"expected_args": { "skill": "pr-fixer", "args": "1234" },
30+
"description": "Punctuation-trailing PR number — trailing period must not be captured"
31+
},
2032
{
2133
"input": "/pr-fixer",
2234
"expected_tool_call": "None",

.claude/skills/scaffold/evals/evals.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
{
99
"input": "add a new integration for PagerDuty",
1010
"expected_tool_call": "Skill",
11-
"expected_args": { "skill": "scaffold" },
12-
"description": "Natural language integration scaffolding request"
11+
"expected_args": { "skill": "scaffold", "args": "integration PagerDuty" },
12+
"description": "Natural language integration scaffolding request — must extract integration name"
1313
},
1414
{
1515
"input": "/scaffold endpoint audit-logs",

.claude/skills/unleash-flag/SKILL.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,12 +169,19 @@ This returns 404 (not 403) when the flag is off, so the endpoint appears not to
169169

170170
### E2E Testing with Feature Flags
171171

172-
When writing E2E tests for flagged features, set the admin token via environment variable (obtain from Unleash UI > API Access, or from deployment secrets):
172+
When writing E2E tests for flagged features, the Unleash admin token must be set as an environment variable. **Never paste or export the token inline in a shell session** — this risks exposing it in shell history, logs, or terminal recordings.
173+
174+
Obtain the token from Unleash UI > API Access or from deployment secrets, then set it using a non-echoing prompt or a secret manager:
173175
```bash
174-
export CYPRESS_UNLEASH_ADMIN_TOKEN='<your-unleash-admin-token>'
176+
# Non-echoing prompt (token not stored in shell history)
177+
read -rs CYPRESS_UNLEASH_ADMIN_TOKEN && export CYPRESS_UNLEASH_ADMIN_TOKEN
175178
```
176179

177-
Alternatively, map it in `e2e/cypress.config.ts`:
180+
In CI, inject it via a secret reference (e.g. GitHub Actions secret, Vault, or sealed secret) — never hard-code or `echo` the value.
181+
182+
> **Note**: When logging token-related errors, use `len(token)` to confirm presence without exposing the value. Never include the full token in error messages, API responses, or commit history.
183+
184+
Map it in `e2e/cypress.config.ts`:
178185
```typescript
179186
env: { UNLEASH_ADMIN_TOKEN: process.env.CYPRESS_UNLEASH_ADMIN_TOKEN }
180187
```

0 commit comments

Comments
 (0)