@prism-d1/cli 1.0.73 → 1.0.74

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.
@@ -12,6 +12,7 @@
12
12
  - Unbounded database queries (no LIMIT, no pagination, no streaming for large result sets)
13
13
  - Disabled security controls (authentication bypassed, authorization checks removed)
14
14
  - Use of `eval()`, `Function()` constructor, or `child_process.exec()` with user input
15
+ - Stub or placeholder implementations (functions that ignore parameters and return hardcoded/empty values)
15
16
 
16
17
  ## Warnings (comment but don't block)
17
18
 
@@ -1,4 +1,4 @@
1
- # prism-eval-gate.yml — AI code quality gate using kiro-cli headless mode.
1
+ # prism-eval-gate.yml -- AI code quality gate using kiro-cli headless mode.
2
2
  #
3
3
  # Copy this file to .github/workflows/prism-eval-gate.yml in your repo.
4
4
  #
@@ -42,49 +42,35 @@ jobs:
42
42
  TEAM_ID=$(jq -r '.team_id // "no_team"' .prism/config.json 2>/dev/null || echo "no_team")
43
43
  echo "team_id=${TEAM_ID}" >> "$GITHUB_OUTPUT"
44
44
 
45
- - name: Identify AI-generated changes
46
- id: detect-ai
47
- env:
48
- BASE_SHA: ${{ github.event.pull_request.base.sha }}
49
- HEAD_SHA: ${{ github.sha }}
50
- run: |
51
- AI_FILES=""
52
- for SHA in $(git rev-list "${BASE_SHA}..${HEAD_SHA}"); do
53
- if git log -1 --format='%B' "${SHA}" | grep -q 'AI-Origin: ai-generated\|AI-Origin: ai-assisted'; then
54
- FILES=$(git diff-tree --no-commit-id --name-only -r "${SHA}" \
55
- | grep -E '\.(ts|js|py|go|java|rs|tsx|jsx)$' \
56
- | grep -vE '\.test\.|\.spec\.|__test__|_test\.' || true)
57
- AI_FILES="${AI_FILES} ${FILES}"
58
- fi
59
- done
60
-
61
- UNIQUE_FILES=$(echo "${AI_FILES}" | tr ' ' '\n' | sort -u | grep -v '^$' | head -30)
62
- FILE_COUNT=$(echo "${UNIQUE_FILES}" | grep -c . || echo "0")
63
-
64
- if [ "${FILE_COUNT}" -eq 0 ]; then
65
- echo "has_ai_changes=false" >> "$GITHUB_OUTPUT"
66
- else
67
- echo "has_ai_changes=true" >> "$GITHUB_OUTPUT"
68
- echo "file_count=${FILE_COUNT}" >> "$GITHUB_OUTPUT"
69
- echo "${UNIQUE_FILES}" > /tmp/ai-changed-files.txt
70
- fi
71
-
72
45
  - name: Kiro code quality review
73
46
  id: review
74
- if: steps.detect-ai.outputs.has_ai_changes == 'true'
75
47
  env:
76
48
  KIRO_API_KEY: ${{ secrets.KIRO_API_KEY }}
77
49
  BASE_SHA: ${{ github.event.pull_request.base.sha }}
78
50
  HEAD_SHA: ${{ github.sha }}
79
51
  run: |
80
- # Fork PRs don't receive secrets — report neutral, never silently pass
52
+ # Trim whitespace/newlines from API key (GitHub Secrets can add trailing chars)
53
+ export KIRO_API_KEY=$(echo -n "${KIRO_API_KEY}" | tr -d '[:space:]')
54
+
55
+ # Fork PRs don't receive secrets -- report neutral, never silently pass
81
56
  if [ "${HAS_KIRO_KEY}" != "true" ]; then
82
- echo "::warning::KIRO_API_KEY unavailable (fork PR or missing secret) — review skipped"
57
+ echo "::warning::KIRO_API_KEY unavailable (fork PR or missing secret) -- review skipped"
58
+ echo "result=SKIPPED" >> "$GITHUB_OUTPUT"
59
+ exit 0
60
+ fi
61
+
62
+ # Get all changed source files in this PR
63
+ FILES=$(git diff --name-only "${BASE_SHA}..${HEAD_SHA}" \
64
+ | grep -E '\.(ts|js|py|go|java|rs|tsx|jsx)$' \
65
+ | grep -vE '\.test\.|\.spec\.|__test__|_test\.' \
66
+ | head -30 | tr '\n' ' ')
67
+
68
+ if [ -z "${FILES}" ]; then
69
+ echo "No source files changed -- skipping review"
83
70
  echo "result=SKIPPED" >> "$GITHUB_OUTPUT"
84
71
  exit 0
85
72
  fi
86
73
 
87
- FILES=$(cat /tmp/ai-changed-files.txt | tr '\n' ' ')
88
74
  DIFF=$(git diff "${BASE_SHA}..${HEAD_SHA}" -- ${FILES})
89
75
 
90
76
  # Find spec reference from commit trailers
@@ -95,22 +81,24 @@ jobs:
95
81
  fi
96
82
 
97
83
  # Run kiro-cli in headless mode
98
- REVIEW_OUTPUT=$(echo "${DIFF}" | kiro-cli chat --no-interactive \
99
- --trust-tools=read,grep \
100
- --model claude-haiku-4.5 \
101
- "You are a code reviewer running in CI. Review this PR diff for code quality issues.
102
-
103
- Changed files: ${FILES}
84
+ echo "::group::kiro-cli version"
85
+ which kiro-cli && kiro-cli --version || echo "kiro-cli not found on PATH"
86
+ echo "::endgroup::"
104
87
 
105
- ${SPEC_CONTEXT}
88
+ echo "::group::kiro-cli smoke test"
89
+ echo "Say hello in JSON" | kiro-cli chat --no-interactive --model auto || echo "SMOKE TEST FAILED"
90
+ echo "::endgroup::"
106
91
 
107
- Read the actual source files for full context (imports, related functions, tests).
108
- Follow the review rules in .kiro/steering/code-review.md if it exists.
92
+ echo "Reviewing ${FILES}"
109
93
 
110
- Focus on: correctness bugs, missing error handling, injection risks, performance anti-patterns, type safety violations, and hallucinated imports/APIs that don't exist.
94
+ # Keep prompt short -- kiro-cli v2.16.2 has a bug putting stdin into HTTP headers
95
+ # on long content. Use a minimal CLI arg prompt and let kiro read files itself.
96
+ git diff "${BASE_SHA}..${HEAD_SHA}" -- ${FILES} > /tmp/pr-diff.patch
111
97
 
112
- Output ONLY valid JSON on a single line (no markdown fencing, no explanation):
113
- {\"findings\":[{\"file\":\"path\",\"line\":1,\"severity\":\"high|medium|low\",\"category\":\"security|correctness|performance|maintainability|reliability\",\"message\":\"description\"}],\"score\":0.0,\"summary\":\"one line\"}" 2>/dev/null) || true
98
+ REVIEW_OUTPUT=$(kiro-cli chat --no-interactive \
99
+ --trust-all-tools \
100
+ --model auto \
101
+ "Review /tmp/pr-diff.patch for code quality. Read it, then output ONLY JSON: {\"findings\":[{\"file\":\"path\",\"line\":1,\"severity\":\"high|medium|low\",\"category\":\"str\",\"message\":\"str\"}],\"score\":0.0,\"summary\":\"str\"}") || true
114
102
 
115
103
  # Strip ANSI escapes, join lines, extract the last JSON object
116
104
  CLEANED=$(echo "${REVIEW_OUTPUT}" | sed 's/\x1b\[[0-9;?]*[a-zA-Z]//g' | tr -d '\r')
@@ -118,7 +106,15 @@ jobs:
118
106
 
119
107
  if [ -z "${REVIEW_JSON}" ] || ! echo "${REVIEW_JSON}" | jq -e '.score' > /dev/null 2>&1; then
120
108
  # FAIL CLOSED: a gate that can't evaluate must not pass
121
- echo "::error::Could not parse kiro-cli review output — failing closed"
109
+ echo "::group::Debug: raw kiro-cli output (first 2000 chars)"
110
+ echo "${REVIEW_OUTPUT:-<empty>}" | head -c 2000
111
+ echo ""
112
+ echo "::endgroup::"
113
+ echo "::group::Debug: cleaned output"
114
+ echo "${CLEANED:-<empty>}" | head -c 2000
115
+ echo ""
116
+ echo "::endgroup::"
117
+ echo "::error::Could not parse kiro-cli review output -- failing closed"
122
118
  echo "result=ERROR" >> "$GITHUB_OUTPUT"
123
119
  exit 0
124
120
  fi
@@ -127,7 +123,7 @@ jobs:
127
123
  FINDINGS=$(echo "${REVIEW_JSON}" | jq '.findings | length')
128
124
  HIGH=$(echo "${REVIEW_JSON}" | jq '[.findings[] | select(.severity=="high")] | length')
129
125
  MEDIUM=$(echo "${REVIEW_JSON}" | jq '[.findings[] | select(.severity=="medium")] | length')
130
- # Single line, quotes stripped — safe for GITHUB_OUTPUT and downstream env use
126
+ # Single line, quotes stripped -- safe for GITHUB_OUTPUT and downstream env use
131
127
  SUMMARY=$(echo "${REVIEW_JSON}" | jq -r '.summary // "No summary"' | head -1 | tr -d '"`'"'" | cut -c1-200)
132
128
 
133
129
  echo "score=${SCORE}" >> "$GITHUB_OUTPUT"
@@ -137,7 +133,7 @@ jobs:
137
133
  echo "summary=${SUMMARY}" >> "$GITHUB_OUTPUT"
138
134
  echo "${REVIEW_JSON}" > /tmp/kiro-review.json
139
135
 
140
- # Determine pass/fail (awk instead of bc — no extra package needed)
136
+ # Determine pass/fail (awk instead of bc -- no extra package needed)
141
137
  PASS=$(awk -v s="${SCORE}" 'BEGIN { print (s >= 0.82) ? "true" : "false" }')
142
138
  if [ "${HIGH}" -gt 0 ] || [ "${PASS}" != "true" ]; then
143
139
  echo "result=FAIL" >> "$GITHUB_OUTPUT"
@@ -149,7 +145,6 @@ jobs:
149
145
  if: always()
150
146
  uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
151
147
  env:
152
- HAS_AI: ${{ steps.detect-ai.outputs.has_ai_changes }}
153
148
  REVIEW_SCORE: ${{ steps.review.outputs.score }}
154
149
  REVIEW_FINDINGS: ${{ steps.review.outputs.findings }}
155
150
  REVIEW_HIGH: ${{ steps.review.outputs.high }}
@@ -159,20 +154,16 @@ jobs:
159
154
  with:
160
155
  script: |
161
156
  const fs = require('fs');
162
- // All values read from env — never interpolate ${{ }} into script source
157
+ // All values read from env -- never interpolate secrets into script source
163
158
  // (LLM-generated text could contain quotes/backticks = script injection)
164
- const hasAI = process.env.HAS_AI === 'true';
165
159
 
166
160
  let body;
167
- if (!hasAI) {
168
- body = '✅ **PRISM Eval Gate** — No AI-generated code detected. Skipped.';
161
+ const result = process.env.REVIEW_RESULT || 'ERROR';
162
+ if (result === 'SKIPPED') {
163
+ body = '⚠️ **PRISM Eval Gate** -- Review skipped (no source files changed or no API key on fork PRs).';
164
+ } else if (result === 'ERROR') {
165
+ body = '❌ **PRISM Eval Gate** -- Review output could not be parsed. Failing closed; re-run the workflow or review manually.';
169
166
  } else {
170
- const result = process.env.REVIEW_RESULT || 'ERROR';
171
- if (result === 'SKIPPED') {
172
- body = '⚠️ **PRISM Eval Gate** — Review unavailable (no API key on fork PRs). A maintainer must review manually.';
173
- } else if (result === 'ERROR') {
174
- body = '❌ **PRISM Eval Gate** — Review output could not be parsed. Failing closed; re-run the workflow or review manually.';
175
- } else {
176
167
  const score = process.env.REVIEW_SCORE || '?';
177
168
  const findings = process.env.REVIEW_FINDINGS || '0';
178
169
  const high = process.env.REVIEW_HIGH || '0';
@@ -192,7 +183,7 @@ jobs:
192
183
  }
193
184
  } catch(e) { /* no detail available */ }
194
185
 
195
- body = `## ${emoji} PRISM Eval Gate — ${result}\n\n` +
186
+ body = `## ${emoji} PRISM Eval Gate -- ${result}\n\n` +
196
187
  `**Score**: ${score} | **Findings**: ${findings} (${high} high, ${medium} medium)\n\n` +
197
188
  `**Summary**: ${summary}\n\n`;
198
189
 
@@ -200,8 +191,7 @@ jobs:
200
191
  body += `| File | Line | Severity | Category | Issue |\n|---|---|---|---|---|\n${table}\n\n`;
201
192
  }
202
193
 
203
- body += `> Powered by kiro-cli headless • Model: claude-haiku-4.5 • Threshold: 0.82`;
204
- }
194
+ body += `> Powered by kiro-cli headless - Model: claude-haiku-4.5 - Threshold: 0.82`;
205
195
  }
206
196
 
207
197
  const { data: comments } = await github.rest.issues.listComments({
@@ -217,9 +207,9 @@ jobs:
217
207
  await github.rest.issues.createComment({ ...params, issue_number: context.issue.number });
218
208
  }
219
209
 
220
- - name: Configure AWS credentials (OIDC) — for metrics + security scan
210
+ - name: Configure AWS credentials (OIDC) -- for metrics + security scan
221
211
  id: aws-creds
222
- if: steps.detect-ai.outputs.has_ai_changes == 'true' && env.METRICS_ROLE_ARN != ''
212
+ if: env.METRICS_ROLE_ARN != ''
223
213
  uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df # v4.2.1
224
214
  with:
225
215
  role-to-assume: ${{ env.METRICS_ROLE_ARN }}
@@ -227,7 +217,7 @@ jobs:
227
217
  continue-on-error: true
228
218
 
229
219
  - name: Emit prism.d1.eval event
230
- if: steps.detect-ai.outputs.has_ai_changes == 'true' && steps.aws-creds.outcome == 'success'
220
+ if: steps.aws-creds.outcome == 'success'
231
221
  env:
232
222
  AWS_REGION: us-west-2
233
223
  TEAM_ID: ${{ steps.prism-config.outputs.team_id }}
@@ -262,9 +252,9 @@ jobs:
262
252
  aws events put-events --region us-west-2 --entries \
263
253
  "[{\"Source\":\"prism.d1.velocity\",\"DetailType\":\"prism.d1.eval\",\"EventBusName\":\"prism-d1-metrics\",\"Detail\":$(echo "${DETAIL}" | jq -Rs '.')}]" || true
264
254
 
265
- - name: AWS Continuum security scan (Tier 2 — deterministic)
255
+ - name: AWS Continuum security scan (Tier 2 -- deterministic)
266
256
  id: security-gate
267
- if: steps.detect-ai.outputs.has_ai_changes == 'true' && steps.aws-creds.outcome == 'success'
257
+ if: steps.aws-creds.outcome == 'success'
268
258
  env:
269
259
  AWS_REGION: us-west-2
270
260
  BASE_SHA: ${{ github.event.pull_request.base.sha }}
@@ -293,7 +283,7 @@ jobs:
293
283
  REPO_SLUG=$(echo "${REPO}" | tr '/' '-')
294
284
  CODE_REVIEW_ID=$(aws ssm get-parameter --name "/prism/continuum/code-review-id/${REPO_SLUG}" --query Parameter.Value --output text 2>/dev/null || echo "")
295
285
  if [ -z "$CODE_REVIEW_ID" ]; then
296
- echo "::warning::No Code Review resource for ${REPO_SLUG} — run 'prism-cli securityagent setup' first. Skipping."
286
+ echo "::warning::No Code Review resource for ${REPO_SLUG} -- run 'prism-cli securityagent setup' first. Skipping."
297
287
  echo "findings=0" >> "$GITHUB_OUTPUT"
298
288
  echo "skipped=true" >> "$GITHUB_OUTPUT"
299
289
  exit 0
@@ -327,7 +317,7 @@ jobs:
327
317
  done
328
318
 
329
319
  if [ "$STATUS" != "COMPLETED" ]; then
330
- echo "::warning::Continuum scan did not complete (status: ${STATUS}) — treating as skipped"
320
+ echo "::warning::Continuum scan did not complete (status: ${STATUS}) -- treating as skipped"
331
321
  echo "findings=0" >> "$GITHUB_OUTPUT"
332
322
  echo "skipped=true" >> "$GITHUB_OUTPUT"
333
323
  exit 0
@@ -354,11 +344,7 @@ jobs:
354
344
  fi
355
345
 
356
346
  - name: Fail on eval gate failure
357
- if: >-
358
- steps.review.outputs.result == 'FAIL' ||
359
- steps.review.outputs.result == 'ERROR' ||
360
- (steps.security-gate.outputs.skipped != 'true' &&
361
- (steps.security-gate.outputs.critical > 0 || steps.security-gate.outputs.high > 0))
347
+ if: ${{ steps.review.outputs.result == 'FAIL' || steps.review.outputs.result == 'ERROR' || (steps.security-gate.outputs.skipped != 'true' && (steps.security-gate.outputs.critical != '0' || steps.security-gate.outputs.high != '0')) }}
362
348
  env:
363
349
  REVIEW_RESULT: ${{ steps.review.outputs.result }}
364
350
  REVIEW_HIGH: ${{ steps.review.outputs.high }}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prism-d1/cli",
3
- "version": "1.0.73",
3
+ "version": "1.0.74",
4
4
  "description": "PRISM D1 Velocity CLI — AI development lifecycle assessment tool",
5
5
  "author": "andklee",
6
6
  "engines": {