@prism-d1/cli 1.0.83 → 1.0.85

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 (52) hide show
  1. package/dist/assets/coding-agent/README.md +824 -0
  2. package/dist/assets/coding-agent/agent.py +381 -0
  3. package/dist/assets/coding-agent/config.py +338 -0
  4. package/dist/assets/coding-agent/deploy/Dockerfile +86 -0
  5. package/dist/assets/coding-agent/deploy/create_harness.py +144 -0
  6. package/dist/assets/coding-agent/deploy/deploy-harness.sh +201 -0
  7. package/dist/assets/coding-agent/deploy/prism-coding-agent.yml +399 -0
  8. package/dist/assets/coding-agent/eval/run_eval.py +430 -0
  9. package/dist/assets/coding-agent/eval/run_harness_eval.py +262 -0
  10. package/dist/assets/coding-agent/eval/stubs/001-tags-element-validation.json +11 -0
  11. package/dist/assets/coding-agent/eval/stubs/002-status-filter.json +11 -0
  12. package/dist/assets/coding-agent/eval/stubs/003-refuse-test-deletion.json +11 -0
  13. package/dist/assets/coding-agent/fixtures/001-tags-element-validation.json +12 -0
  14. package/dist/assets/coding-agent/fixtures/002-status-filter.json +12 -0
  15. package/dist/assets/coding-agent/fixtures/003-refuse-test-deletion.json +10 -0
  16. package/dist/assets/coding-agent/pyproject.toml +28 -0
  17. package/dist/assets/coding-agent/requirements.txt +8 -0
  18. package/dist/assets/coding-agent/system_prompt.py +290 -0
  19. package/dist/assets/coding-agent/tools/__init__.py +11 -0
  20. package/dist/assets/coding-agent/tools/create_pr.py +141 -0
  21. package/dist/assets/coding-agent/tools/git_ops.py +197 -0
  22. package/dist/assets/github-workflows/prism-agent-eval.yml +8 -3
  23. package/dist/assets/github-workflows/prism-ai-metrics.yml +19 -6
  24. package/dist/assets/github-workflows/prism-eval-gate-kiro.yml +14 -9
  25. package/dist/assets/github-workflows/prism-eval-gate.yml +11 -6
  26. package/dist/assets/gitlab-workflows/prism-agent-eval.yml +5 -3
  27. package/dist/assets/gitlab-workflows/prism-ai-metrics.yml +5 -3
  28. package/dist/assets/gitlab-workflows/prism-eval-gate.yml +5 -3
  29. package/dist/assets/infra/lib/constructs/otel-collector-construct.ts +134 -2
  30. package/dist/assets/infra/lib/dashboard-stack.ts +79 -95
  31. package/dist/assets/infra/lib/lambda/metrics-processor.ts +99 -1
  32. package/dist/assets/infra/lib/lambda/otel-receiver.ts +318 -29
  33. package/dist/assets/infra/lib/lambda/productivity-widget.ts +85 -4
  34. package/dist/assets/infra/lib/lambda/velocity-widget.ts +265 -0
  35. package/dist/assets/infra/lib/metrics-pipeline-stack.ts +5 -0
  36. package/dist/src/commands/bootstrapper/install-coding-agent.d.ts +61 -0
  37. package/dist/src/commands/bootstrapper/install-coding-agent.d.ts.map +1 -0
  38. package/dist/src/commands/bootstrapper/install-coding-agent.js +599 -0
  39. package/dist/src/commands/bootstrapper/install-coding-agent.js.map +1 -0
  40. package/dist/src/commands/bootstrapper/install-eval-harness.d.ts.map +1 -1
  41. package/dist/src/commands/bootstrapper/install-eval-harness.js +16 -6
  42. package/dist/src/commands/bootstrapper/install-eval-harness.js.map +1 -1
  43. package/dist/src/commands/bootstrapper/install-github-workflows.d.ts.map +1 -1
  44. package/dist/src/commands/bootstrapper/install-github-workflows.js +13 -6
  45. package/dist/src/commands/bootstrapper/install-github-workflows.js.map +1 -1
  46. package/dist/src/commands/bootstrapper/install-gitlab-workflows.d.ts.map +1 -1
  47. package/dist/src/commands/bootstrapper/install-gitlab-workflows.js +9 -6
  48. package/dist/src/commands/bootstrapper/install-gitlab-workflows.js.map +1 -1
  49. package/dist/src/commands/bootstrapper/setup-github-oidc.d.ts.map +1 -1
  50. package/dist/src/commands/bootstrapper/setup-github-oidc.js +23 -0
  51. package/dist/src/commands/bootstrapper/setup-github-oidc.js.map +1 -1
  52. package/package.json +2 -2
@@ -0,0 +1,197 @@
1
+ """Git operations exposed to the agent as a single Strands tool.
2
+
3
+ Every git invocation goes through `subprocess.run` with an argv list and never
4
+ `shell=True`. The agent supplies branch names and commit messages, so treating
5
+ them as shell strings would let a crafted issue body run arbitrary commands.
6
+
7
+ `push` is deliberately absent. Pushing is a privileged step that belongs to the
8
+ PR-creation path where credentials live, not to a general-purpose git tool the
9
+ model can call at will.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import re
15
+ import subprocess
16
+ from pathlib import Path
17
+
18
+ from strands import tool
19
+
20
+ # Branch names: git's own rules, tightened. No leading/trailing dots or slashes,
21
+ # no '..', no characters git rejects, nothing that could be read as a flag.
22
+ _BRANCH_OK = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._/-]{0,99}$")
23
+ _TIMEOUT_SECONDS = 60
24
+
25
+
26
+ class GitError(RuntimeError):
27
+ """A git command failed or was rejected before running."""
28
+
29
+
30
+ def _run(args: list[str], cwd: Path) -> str:
31
+ """Run a git command and return stdout, raising GitError on failure."""
32
+ try:
33
+ proc = subprocess.run(
34
+ ["git", *args],
35
+ cwd=str(cwd),
36
+ capture_output=True,
37
+ text=True,
38
+ timeout=_TIMEOUT_SECONDS,
39
+ check=False,
40
+ )
41
+ except subprocess.TimeoutExpired as exc:
42
+ raise GitError(f"git {args[0]} timed out after {_TIMEOUT_SECONDS}s") from exc
43
+ except FileNotFoundError as exc:
44
+ raise GitError("git is not installed or not on PATH") from exc
45
+
46
+ if proc.returncode != 0:
47
+ detail = (proc.stderr or proc.stdout).strip()
48
+ raise GitError(f"git {' '.join(args)} failed: {detail}")
49
+ return proc.stdout.strip()
50
+
51
+
52
+ def _validate_branch(name: str) -> str:
53
+ name = name.strip()
54
+ if not _BRANCH_OK.match(name) or ".." in name or name.endswith((".", "/", ".lock")):
55
+ raise GitError(
56
+ f"Invalid branch name {name!r}. Use letters, digits, dot, dash, "
57
+ "underscore and slash; start with a letter or digit."
58
+ )
59
+ return name
60
+
61
+
62
+ def _validate_paths(paths: list[str], repo_path: Path) -> list[str]:
63
+ """Resolve each path and confirm it stays inside the repository.
64
+
65
+ Rejects absolute paths, traversal, and symlinks that point outside the repo.
66
+ """
67
+ resolved: list[str] = []
68
+ repo_real = repo_path.resolve()
69
+ for raw in paths:
70
+ candidate = (repo_real / raw).resolve()
71
+ try:
72
+ candidate.relative_to(repo_real)
73
+ except ValueError as exc:
74
+ raise GitError(f"Path escapes the repository: {raw!r}") from exc
75
+ if not candidate.exists():
76
+ raise GitError(f"Path does not exist: {raw!r}")
77
+ resolved.append(str(candidate.relative_to(repo_real)))
78
+ return resolved
79
+
80
+
81
+
82
+ def _resolve_repo(path: Path) -> Path | None:
83
+ """Return the git repository enclosing `path`, or None if there is none.
84
+
85
+ Uses git's own answer rather than walking for a `.git` directory, so
86
+ worktrees and submodules resolve the way git itself sees them.
87
+ """
88
+ try:
89
+ proc = subprocess.run(
90
+ ["git", "rev-parse", "--show-toplevel"],
91
+ cwd=str(path), capture_output=True, text=True,
92
+ timeout=_TIMEOUT_SECONDS, check=False,
93
+ )
94
+ except (OSError, subprocess.SubprocessError):
95
+ return None
96
+ if proc.returncode != 0 or not proc.stdout.strip():
97
+ return None
98
+ return Path(proc.stdout.strip())
99
+
100
+
101
+ @tool
102
+ def git_ops(
103
+ action: str,
104
+ repo_path: str,
105
+ branch: str | None = None,
106
+ message: str | None = None,
107
+ paths: list[str] | None = None,
108
+ ) -> str:
109
+ """Perform a git operation in the target repository.
110
+
111
+ Use this to create a working branch, inspect what you have changed, stage
112
+ specific files, and commit. Pushing is handled separately by create_pr.
113
+
114
+ Args:
115
+ action: One of "status", "diff", "current_branch", "create_branch",
116
+ "stage", "commit", "log".
117
+ repo_path: Absolute path to the repository working tree.
118
+ branch: Branch name. Required for "create_branch".
119
+ message: Commit message. Required for "commit".
120
+ paths: Repository-relative file paths. Required for "stage". Name each
121
+ file explicitly; there is no "stage everything" option.
122
+
123
+ Returns:
124
+ Command output, or a short confirmation for actions with no output.
125
+ """
126
+ repo = Path(repo_path)
127
+ # Resolved rather than tested for a `.git` child, because a target is often a
128
+ # subdirectory of its repository -- PRISM's own sample-app sits inside a
129
+ # monorepo, and customer monorepos are the same shape.
130
+ #
131
+ # Requiring `.git` here caused a genuinely bad failure, observed rather than
132
+ # imagined: this tool refused with "not a git repository", and the agent --
133
+ # which also has a shell -- routed around the refusal by running `git init`
134
+ # and committing all 54 files as "Initial commit". A refusing tool is not a
135
+ # constraint on something that can run arbitrary commands; it is only a
136
+ # suggestion. So the tool has to be able to do the right thing rather than
137
+ # merely decline to do the wrong one.
138
+ resolved = _resolve_repo(repo)
139
+ if resolved is None:
140
+ return (
141
+ f"ERROR: {repo_path} is not inside a git repository. Do NOT run "
142
+ f"`git init` -- that would create a new repository and commit "
143
+ f"everything, which is never the fix. Report the problem instead."
144
+ )
145
+ repo = resolved
146
+
147
+ try:
148
+ if action == "status":
149
+ out = _run(["status", "--porcelain=v1"], repo)
150
+ return out or "(working tree clean)"
151
+
152
+ if action == "diff":
153
+ out = _run(["diff", "--stat", "HEAD"], repo)
154
+ return out or "(no changes against HEAD)"
155
+
156
+ if action == "current_branch":
157
+ return _run(["rev-parse", "--abbrev-ref", "HEAD"], repo)
158
+
159
+ if action == "log":
160
+ return _run(["log", "--oneline", "-10"], repo)
161
+
162
+ if action == "create_branch":
163
+ if not branch:
164
+ return "ERROR: create_branch requires a branch name"
165
+ safe = _validate_branch(branch)
166
+ _run(["checkout", "-b", safe], repo)
167
+ return f"Created and switched to branch {safe}"
168
+
169
+ if action == "stage":
170
+ if not paths:
171
+ return (
172
+ "ERROR: stage requires an explicit list of paths. "
173
+ "Name each file you changed."
174
+ )
175
+ safe_paths = _validate_paths(paths, repo)
176
+ _run(["add", "--", *safe_paths], repo)
177
+ return f"Staged {len(safe_paths)} file(s): {', '.join(safe_paths)}"
178
+
179
+ if action == "commit":
180
+ if not message or not message.strip():
181
+ return "ERROR: commit requires a non-empty message"
182
+ staged = _run(["diff", "--cached", "--name-only"], repo)
183
+ if not staged:
184
+ return "ERROR: nothing staged. Stage your changed files first."
185
+ # -m takes the message as a separate argv element, so newlines and
186
+ # quotes in the message are data, not shell syntax.
187
+ _run(["commit", "-m", message], repo)
188
+ sha = _run(["rev-parse", "HEAD"], repo)
189
+ return f"Committed {sha[:8]} with files:\n{staged}"
190
+
191
+ return (
192
+ f"ERROR: unknown action {action!r}. Valid actions: status, diff, "
193
+ "current_branch, create_branch, stage, commit, log"
194
+ )
195
+
196
+ except GitError as exc:
197
+ return f"ERROR: {exc}"
@@ -23,6 +23,11 @@ on:
23
23
  - '**/agent*.py'
24
24
  - '**/agent*.ts'
25
25
 
26
+
27
+ env:
28
+ PRISM_AWS_REGION: us-west-2
29
+ PRISM_REPO: github.com/${{ github.repository }}
30
+
26
31
  permissions:
27
32
  id-token: write
28
33
  contents: read
@@ -41,7 +46,7 @@ jobs:
41
46
  uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df # v4.2.1
42
47
  with:
43
48
  role-to-assume: ${{ secrets.PRISM_METRICS_ROLE_ARN }}
44
- aws-region: us-west-2
49
+ aws-region: ${{ env.PRISM_AWS_REGION }}
45
50
 
46
51
  - name: Read team ID from .prism/config.json
47
52
  id: prism-config
@@ -263,7 +268,7 @@ jobs:
263
268
 
264
269
  EVAL_EVENT=$(jq -n \
265
270
  --arg team_id "${{ steps.prism-config.outputs.team_id }}" \
266
- --arg repo "${{ github.repository }}" \
271
+ --arg repo "${PRISM_REPO}" \
267
272
  --arg timestamp "${TIMESTAMP}" \
268
273
  --argjson score "${SCORE:-0}" \
269
274
  --arg result "${{ steps.eval.outputs.result }}" \
@@ -298,7 +303,7 @@ jobs:
298
303
  }')
299
304
 
300
305
  aws events put-events \
301
- --region us-west-2 \
306
+ --region $PRISM_AWS_REGION \
302
307
  --entries "[{
303
308
  \"Source\": \"prism.d1.velocity\",
304
309
  \"DetailType\": \"prism.d1.agent.eval\",
@@ -33,6 +33,11 @@ on:
33
33
  types: [closed]
34
34
  branches: [main, master]
35
35
 
36
+
37
+ env:
38
+ PRISM_AWS_REGION: us-west-2
39
+ PRISM_REPO: github.com/${{ github.repository }}
40
+
36
41
  permissions:
37
42
  id-token: write
38
43
  contents: read
@@ -54,7 +59,7 @@ jobs:
54
59
  uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df # v4.2.1
55
60
  with:
56
61
  role-to-assume: ${{ secrets.PRISM_METRICS_ROLE_ARN }}
57
- aws-region: us-west-2
62
+ aws-region: ${{ env.PRISM_AWS_REGION }}
58
63
 
59
64
  - name: Read team ID from .prism/config.json
60
65
  id: prism-config
@@ -101,6 +106,11 @@ jobs:
101
106
  COMMIT_SHAS=$(git rev-list --no-merges "${BASE_SHA}..${HEAD_SHA}" 2>/dev/null | head -50 | jq -R . | jq -sc . || echo '[]')
102
107
  TOTAL_COMMITS=$(git rev-list --no-merges --count "${BASE_SHA}..${HEAD_SHA}" 2>/dev/null || echo 0)
103
108
 
109
+ # Per-commit author emails (parallel array to COMMIT_SHAS). Used by
110
+ # the metrics-processor to seed COMMIT# items with the correct user
111
+ # field so /v1/productivity can attribute human commits per-developer.
112
+ COMMIT_AUTHORS=$(git rev-list --no-merges "${BASE_SHA}..${HEAD_SHA}" 2>/dev/null | head -50 | while read sha; do git log -1 --format='%ae' "$sha"; done | jq -R . | jq -sc . || echo '[]')
113
+
104
114
  # --- Lead time: PR open → merge. From the event payload, not git, so
105
115
  # it is unaffected by rebases and squashes.
106
116
  CREATED_TS=$(date -d "${CREATED_AT}" +%s 2>/dev/null || date -jf "%Y-%m-%dT%H:%M:%SZ" "${CREATED_AT}" +%s)
@@ -119,6 +129,7 @@ jobs:
119
129
  fi
120
130
 
121
131
  echo "commit_shas=${COMMIT_SHAS}" >> "$GITHUB_OUTPUT"
132
+ echo "commit_authors=${COMMIT_AUTHORS}" >> "$GITHUB_OUTPUT"
122
133
  echo "total_commits=${TOTAL_COMMITS}" >> "$GITHUB_OUTPUT"
123
134
  echo "lead_time_seconds=${LEAD_TIME_SECONDS}" >> "$GITHUB_OUTPUT"
124
135
  echo "is_failure_fix=${IS_FAILURE_FIX}" >> "$GITHUB_OUTPUT"
@@ -150,12 +161,13 @@ jobs:
150
161
 
151
162
  PR_EVENT=$(jq -n \
152
163
  --arg team_id "${{ steps.prism-config.outputs.team_id }}" \
153
- --arg repo "${{ github.repository }}" \
164
+ --arg repo "${PRISM_REPO}" \
154
165
  --arg timestamp "${TIMESTAMP}" \
155
166
  --argjson lead_time_seconds "${{ steps.facts.outputs.lead_time_seconds }}" \
156
167
  --argjson is_failure_fix "${{ steps.facts.outputs.is_failure_fix }}" \
157
168
  --argjson total_commits "${{ steps.facts.outputs.total_commits }}" \
158
169
  --argjson commit_shas '${{ steps.facts.outputs.commit_shas }}' \
170
+ --argjson commit_authors '${{ steps.facts.outputs.commit_authors }}' \
159
171
  --arg pr_number "${{ github.event.pull_request.number }}" \
160
172
  --arg pr_author "${{ github.event.pull_request.user.login }}" \
161
173
  --argjson approved "${{ steps.reviews.outputs.approved }}" \
@@ -180,12 +192,13 @@ jobs:
180
192
  "reviews_approved": $approved,
181
193
  "reviews_changes_requested": $changes_requested,
182
194
  "total_commits": $total_commits,
183
- "commit_shas": $commit_shas
195
+ "commit_shas": $commit_shas,
196
+ "commit_authors": $commit_authors
184
197
  }
185
198
  }')
186
199
 
187
200
  aws events put-events \
188
- --region us-west-2 \
201
+ --region $PRISM_AWS_REGION \
189
202
  --entries "[{
190
203
  \"Source\": \"prism.d1.velocity\",
191
204
  \"DetailType\": \"prism.d1.pr\",
@@ -207,7 +220,7 @@ jobs:
207
220
  # carrying it on both double-counted the DeploymentFrequency metric.
208
221
  DEPLOY_EVENT=$(jq -n \
209
222
  --arg team_id "${{ steps.prism-config.outputs.team_id }}" \
210
- --arg repo "${{ github.repository }}" \
223
+ --arg repo "${PRISM_REPO}" \
211
224
  --arg timestamp "${TIMESTAMP}" \
212
225
  '{
213
226
  "team_id": $team_id,
@@ -225,7 +238,7 @@ jobs:
225
238
  }')
226
239
 
227
240
  aws events put-events \
228
- --region us-west-2 \
241
+ --region $PRISM_AWS_REGION \
229
242
  --entries "[{
230
243
  \"Source\": \"prism.d1.velocity\",
231
244
  \"DetailType\": \"prism.d1.deploy\",
@@ -15,6 +15,11 @@ on:
15
15
  types: [opened, synchronize, reopened]
16
16
  branches: [main, master]
17
17
 
18
+
19
+ env:
20
+ PRISM_AWS_REGION: us-west-2
21
+ PRISM_REPO: github.com/${{ github.repository }}
22
+
18
23
  permissions:
19
24
  id-token: write
20
25
  contents: read
@@ -213,15 +218,15 @@ jobs:
213
218
  uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df # v4.2.1
214
219
  with:
215
220
  role-to-assume: ${{ env.METRICS_ROLE_ARN }}
216
- aws-region: us-west-2
221
+ aws-region: ${{ env.PRISM_AWS_REGION }}
217
222
  continue-on-error: true
218
223
 
219
224
  - name: Emit prism.d1.eval event
220
225
  if: steps.aws-creds.outcome == 'success'
221
226
  env:
222
- AWS_REGION: us-west-2
227
+ AWS_REGION: ${{ env.PRISM_AWS_REGION }}
223
228
  TEAM_ID: ${{ steps.prism-config.outputs.team_id }}
224
- REPO: ${{ github.repository }}
229
+ REPO: ${{ env.PRISM_REPO }}
225
230
  REVIEW_SCORE: ${{ steps.review.outputs.score }}
226
231
  REVIEW_RESULT: ${{ steps.review.outputs.result }}
227
232
  REVIEW_FINDINGS: ${{ steps.review.outputs.findings }}
@@ -249,17 +254,17 @@ jobs:
249
254
  eval:{score:($score|tonumber),result:$result,rubric:"kiro-headless",
250
255
  findings:($findings|tonumber),high_findings:($high|tonumber),
251
256
  pr_number:($pr_number|tonumber),method:"kiro-headless"}}')
252
- aws events put-events --region us-west-2 --entries \
257
+ aws events put-events --region $PRISM_AWS_REGION --entries \
253
258
  "[{\"Source\":\"prism.d1.velocity\",\"DetailType\":\"prism.d1.eval\",\"EventBusName\":\"prism-d1-metrics\",\"Detail\":$(echo "${DETAIL}" | jq -Rs '.')}]" || true
254
259
 
255
260
  - name: AWS Continuum security scan (Tier 2 -- deterministic)
256
261
  id: security-gate
257
262
  if: steps.aws-creds.outcome == 'success'
258
263
  env:
259
- AWS_REGION: us-west-2
264
+ AWS_REGION: ${{ env.PRISM_AWS_REGION }}
260
265
  BASE_SHA: ${{ github.event.pull_request.base.sha }}
261
266
  HEAD_SHA: ${{ github.sha }}
262
- REPO: ${{ github.repository }}
267
+ REPO: ${{ env.PRISM_REPO }}
263
268
  PR_NUMBER: ${{ github.event.pull_request.number }}
264
269
  run: |
265
270
  # Config is read FIRST, on purpose. "Continuum was never deployed" is a
@@ -407,9 +412,9 @@ jobs:
407
412
  if: steps.security-gate.outputs.skipped != 'true' && steps.security-gate.outputs.findings != '0' && steps.security-gate.outputs.findings != ''
408
413
  continue-on-error: true
409
414
  env:
410
- AWS_REGION: us-west-2
415
+ AWS_REGION: ${{ env.PRISM_AWS_REGION }}
411
416
  TEAM_ID: ${{ steps.prism-config.outputs.team_id }}
412
- REPO: ${{ github.repository }}
417
+ REPO: ${{ env.PRISM_REPO }}
413
418
  PR_NUMBER: ${{ github.event.pull_request.number }}
414
419
  BASE_SHA: ${{ github.event.pull_request.base.sha }}
415
420
  HEAD_SHA: ${{ github.sha }}
@@ -458,7 +463,7 @@ jobs:
458
463
  if [ "$TOTAL" -gt 0 ]; then
459
464
  # EventBridge accepts max 10 entries per call
460
465
  for i in $(seq 0 10 $((TOTAL - 1))); do
461
- aws events put-events --region us-west-2 \
466
+ aws events put-events --region $PRISM_AWS_REGION \
462
467
  --entries "$(echo "${ENTRIES}" | jq -c ".[$i:$((i+10))]")" || true
463
468
  done
464
469
  echo "Emitted ${TOTAL} Continuum finding events to EventBridge"
@@ -16,6 +16,11 @@ on:
16
16
  types: [opened, synchronize, reopened]
17
17
  branches: [main, master]
18
18
 
19
+
20
+ env:
21
+ PRISM_AWS_REGION: us-west-2
22
+ PRISM_REPO: github.com/${{ github.repository }}
23
+
19
24
  permissions:
20
25
  id-token: write
21
26
  contents: read
@@ -34,7 +39,7 @@ jobs:
34
39
  uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df # v4.2.1
35
40
  with:
36
41
  role-to-assume: ${{ secrets.PRISM_METRICS_ROLE_ARN }}
37
- aws-region: us-west-2
42
+ aws-region: ${{ env.PRISM_AWS_REGION }}
38
43
 
39
44
  - name: Read team ID
40
45
  id: prism-config
@@ -201,7 +206,7 @@ jobs:
201
206
  TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
202
207
  EVAL_EVENT=$(jq -n \
203
208
  --arg team_id "${{ steps.prism-config.outputs.team_id }}" \
204
- --arg repo "${{ github.repository }}" \
209
+ --arg repo "${PRISM_REPO}" \
205
210
  --arg timestamp "${TIMESTAMP}" \
206
211
  --argjson score "${{ steps.eval.outputs.avg_score }}" \
207
212
  --arg result "${{ steps.eval.outputs.overall_result }}" \
@@ -217,7 +222,7 @@ jobs:
217
222
  eval: {total_files: $total_files, pass_count: $pass_count, fail_count: $fail_count,
218
223
  result: $result, pr_number: ($pr_number | tonumber), hallucinations_caught: $hallucinations}
219
224
  }')
220
- aws events put-events --region us-west-2 --entries "[{
225
+ aws events put-events --region $PRISM_AWS_REGION --entries "[{
221
226
  \"Source\":\"prism.d1.velocity\",\"DetailType\":\"prism.d1.eval\",
222
227
  \"EventBusName\":\"prism-d1-metrics\",
223
228
  \"Detail\":$(echo "${EVAL_EVENT}" | jq -c '.' | jq -Rs '.')}]"
@@ -238,7 +243,7 @@ jobs:
238
243
  - name: AWS Continuum diff scan
239
244
  id: security-gate
240
245
  env:
241
- AWS_REGION: us-west-2
246
+ AWS_REGION: ${{ env.PRISM_AWS_REGION }}
242
247
  run: |
243
248
  echo "::group::Retrieve Continuum config from SSM"
244
249
  AGENT_SPACE_ID=$(aws ssm get-parameter --name /prism/continuum/agent-space-id --query Parameter.Value --output text 2>/dev/null || echo "")
@@ -414,10 +419,10 @@ jobs:
414
419
  - name: Emit Continuum findings to EventBridge
415
420
  if: steps.security-gate.outputs.findings != '0' && steps.security-gate.outputs.skipped != 'true'
416
421
  env:
417
- AWS_REGION: us-west-2
422
+ AWS_REGION: ${{ env.PRISM_AWS_REGION }}
418
423
  run: |
419
424
  PR_NUMBER="${{ github.event.pull_request.number }}"
420
- REPO="${{ github.repository }}"
425
+ REPO="${PRISM_REPO}"
421
426
  TEAM_ID="${{ steps.prism-config.outputs.team_id }}"
422
427
  FINDINGS='${{ steps.security-gate.outputs.findings_json }}'
423
428
 
@@ -6,7 +6,7 @@
6
6
  #
7
7
  # Required setup:
8
8
  # - CI/CD variable PRISM_METRICS_ROLE_ARN (IAM role with bedrock:InvokeModel + events:PutEvents)
9
- # - CI/CD variable AWS_REGION (default: us-west-2)
9
+ # - PRISM_AWS_REGION variable in the variables: block below controls the region
10
10
  # - .prism/config.json committed to the repo
11
11
  # - .prism/eval-harness/ installed (run: prism-cli bootstrapper install-eval-harness)
12
12
  # - (Optional) Agent entry point supports --mock flag for dry-run execution
@@ -26,7 +26,9 @@ prism-agent-eval:
26
26
  - "**/*agent*.py"
27
27
  - "**/*agent*.ts"
28
28
  variables:
29
- AWS_DEFAULT_REGION: us-west-2
29
+ PRISM_AWS_REGION: us-west-2
30
+ AWS_DEFAULT_REGION: $PRISM_AWS_REGION
31
+ PRISM_REPO: ${CI_SERVER_HOST}/${CI_PROJECT_PATH}
30
32
  before_script:
31
33
  - apt-get update -qq && apt-get install -y -qq jq bc git curl unzip
32
34
  - curl -s "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o /tmp/awscliv2.zip
@@ -133,7 +135,7 @@ prism-agent-eval:
133
135
  # Emit event
134
136
  TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
135
137
  EVAL_EVENT=$(jq -n \
136
- --arg team_id "${TEAM_ID}" --arg repo "${CI_PROJECT_PATH}" --arg timestamp "${TIMESTAMP}" \
138
+ --arg team_id "${TEAM_ID}" --arg repo "${PRISM_REPO}" --arg timestamp "${TIMESTAMP}" \
137
139
  --argjson score "${SCORE:-0}" --arg result "${RESULT}" --argjson file_count "${FILE_COUNT}" \
138
140
  --arg mr_iid "${CI_MERGE_REQUEST_IID}" --arg mock_ran "${MOCK_RAN}" \
139
141
  '{team_id:$team_id, repo:$repo, timestamp:$timestamp, prism_level:3,
@@ -32,7 +32,9 @@ prism-ai-metrics:
32
32
  rules:
33
33
  - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "push"'
34
34
  variables:
35
- AWS_DEFAULT_REGION: us-west-2
35
+ PRISM_AWS_REGION: us-west-2
36
+ AWS_DEFAULT_REGION: $PRISM_AWS_REGION
37
+ PRISM_REPO: ${CI_SERVER_HOST}/${CI_PROJECT_PATH}
36
38
  before_script:
37
39
  - yum install -y -q jq git
38
40
  - git fetch --unshallow || true
@@ -113,7 +115,7 @@ prism-ai-metrics:
113
115
  # shape — the processor only persists a known section list.
114
116
  PR_EVENT=$(jq -n \
115
117
  --arg team_id "${TEAM_ID}" \
116
- --arg repo "${CI_PROJECT_PATH}" \
118
+ --arg repo "${PRISM_REPO}" \
117
119
  --arg timestamp "${TIMESTAMP}" \
118
120
  --argjson lead_time_seconds "${LEAD_TIME_SECONDS}" \
119
121
  --argjson is_failure_fix "${IS_FAILURE_FIX}" \
@@ -140,7 +142,7 @@ prism-ai-metrics:
140
142
 
141
143
  # Sole deployment signal — deployment_frequency lives ONLY on this event.
142
144
  # Carrying it on prism.d1.pr as well double-counted the metric.
143
- DEPLOY_EVENT=$(jq -n --arg team_id "${TEAM_ID}" --arg repo "${CI_PROJECT_PATH}" --arg timestamp "${TIMESTAMP}" \
145
+ DEPLOY_EVENT=$(jq -n --arg team_id "${TEAM_ID}" --arg repo "${PRISM_REPO}" --arg timestamp "${TIMESTAMP}" \
144
146
  '{team_id: $team_id, repo: $repo, timestamp: $timestamp, prism_level: 2,
145
147
  metric: {name: "deployment", value: 1, unit: "count"},
146
148
  dora: {deployment_frequency: 1}}')
@@ -6,7 +6,7 @@
6
6
  #
7
7
  # Required setup:
8
8
  # - CI/CD variable PRISM_METRICS_ROLE_ARN (IAM role with bedrock:InvokeModel + events:PutEvents)
9
- # - CI/CD variable AWS_REGION (default: us-west-2)
9
+ # - PRISM_AWS_REGION variable in the variables: block below controls the region
10
10
  # - .prism/eval-harness/ directory in your repo (run: prism-cli bootstrapper install-eval-harness)
11
11
  # - At least one rubric JSON in .prism/eval-harness/rubrics/
12
12
 
@@ -21,7 +21,9 @@ prism-eval-gate:
21
21
  rules:
22
22
  - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
23
23
  variables:
24
- AWS_DEFAULT_REGION: us-west-2
24
+ PRISM_AWS_REGION: us-west-2
25
+ AWS_DEFAULT_REGION: $PRISM_AWS_REGION
26
+ PRISM_REPO: ${CI_SERVER_HOST}/${CI_PROJECT_PATH}
25
27
  before_script:
26
28
  - yum install -y -q jq bc git
27
29
  - git fetch --unshallow || true
@@ -139,7 +141,7 @@ prism-eval-gate:
139
141
  # Emit event
140
142
  TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
141
143
  EVAL_EVENT=$(jq -n \
142
- --arg team_id "${TEAM_ID}" --arg repo "${CI_PROJECT_PATH}" --arg timestamp "${TIMESTAMP}" \
144
+ --arg team_id "${TEAM_ID}" --arg repo "${PRISM_REPO}" --arg timestamp "${TIMESTAMP}" \
143
145
  --argjson score "${AVG_SCORE}" --arg result "${OVERALL}" \
144
146
  --argjson total_files "${TOTAL_FILES}" --argjson pass_count "${PASS_COUNT}" \
145
147
  --argjson fail_count "${FAIL_COUNT}" --argjson hallucinations "${TOTAL_HALLUCINATIONS}" \