qwen-code/packages/web-shell/client/components/artifacts/CodeReviewArtifactDetail.module.css
Shaojin Wen 7dfc554dff
feat(review): Add structured Web Shell review results (#8402)
* feat(review): add Web Shell review artifacts

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* test(web-shell): add code review artifact visual scenario (#8402)

* fix(review): address Web Shell review artifact feedback (#8402)

* save-artifact: document why paths resolve against the daemon workspace
  root (QWEN_CODE_PROJECT_DIR) instead of cwd, and cover the relative-path
  form the skill documents with a test where the two roots differ.
* CLI/renderer contract: the renderer hand-duplicates the findings
  vocabulary and fails closed on unknown values, so name the renderer as a
  second consumer beside the CLI's lists and check in a contract fixture
  generated through the real pipeline (validateFindings -> buildReport ->
  save-artifact) that exercises every source, severity, confidence and
  outcome. Exporting the vocabulary through the SDK stays deferred: it is a
  public cross-package API change beyond this PR's seam.
* resolve-anchors now validates `line` exactly like `findings` does
  (positive safe integer); the two validators in one pipeline no longer
  disagree. Note: an in-flight `.qwen/tmp` findings file carrying `line: 0`
  fails where it previously did not.
* The renderer validates markdownReportPath (relative, no ".." segments,
  .md suffix) before it becomes a readWorkspaceFile call, resets the
  severity/confidence filters when switching artifacts, and surfaces
  heldByMeasurement so a nonzero Held count is attributable.
* save-artifact refuses low effort structurally (choices and library guard)
  instead of by prose, stats the Markdown report before reading it so a
  directory reports "not a file", and the component no longer shadows the
  DOM `document` global.
* The case-insensitive alias test now skips visibly on case-sensitive
  filesystems instead of passing vacuously.
* Comment the kept `turnOutputs.review` key and document the JSON
  companion in the user docs.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(review): address second Web Shell review artifact feedback round (#8402)

---------

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: qwen-code-dev-bot <qwen-code-dev@service.alibaba.com>
2026-08-03 16:08:13 +00:00

248 lines
3.8 KiB
CSS

.root {
display: grid;
gap: 14px;
color: var(--foreground);
}
.summary {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 12px;
padding: 14px;
border: 1px solid var(--border);
border-radius: 8px;
background: color-mix(in srgb, var(--accent) 45%, transparent);
}
.eyebrow {
color: var(--muted-foreground);
font-size: 11px;
font-weight: 600;
letter-spacing: 0.04em;
text-transform: uppercase;
}
.verdict {
margin: 4px 0;
font-size: 18px;
overflow-wrap: anywhere;
}
.meta,
.path {
color: var(--muted-foreground);
font-size: 12px;
overflow-wrap: anywhere;
}
.metrics {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(86px, 1fr));
gap: 8px;
}
.metric {
display: grid;
gap: 2px;
padding: 9px;
border: 1px solid var(--border);
border-radius: 6px;
}
.metric strong {
font-size: 18px;
}
.metric span {
color: var(--muted-foreground);
font-size: 11px;
}
.caps {
display: flex;
align-items: baseline;
gap: 10px;
padding: 9px 11px;
border-left: 3px solid var(--border);
background: color-mix(in srgb, var(--muted) 65%, transparent);
font-size: 13px;
overflow-wrap: anywhere;
}
.filters {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.filters label {
display: grid;
gap: 4px;
color: var(--muted-foreground);
font-size: 12px;
}
.filters select {
min-width: 150px;
padding: 7px 9px;
border: 1px solid var(--border);
border-radius: 6px;
background: var(--background);
color: var(--foreground);
font: inherit;
}
.filters select:focus-visible,
.primaryButton:focus-visible,
.secondaryButton:focus-visible {
outline: 2px solid var(--ring);
outline-offset: 2px;
}
.findings {
display: grid;
gap: 10px;
}
.finding {
display: grid;
gap: 10px;
padding: 13px;
border: 1px solid var(--border);
border-radius: 8px;
}
.finding h3,
.detailBlock p {
margin: 0;
}
.finding h3 {
font-size: 15px;
overflow-wrap: anywhere;
}
.findingHeader {
display: flex;
flex-wrap: wrap;
gap: 6px 10px;
color: var(--muted-foreground);
font-size: 11px;
}
.severity {
color: var(--foreground);
font-weight: 700;
}
.detailBlock {
display: grid;
gap: 4px;
font-size: 13px;
}
.detailBlock strong {
color: var(--muted-foreground);
font-size: 11px;
text-transform: uppercase;
}
.detailBlock ul {
display: grid;
gap: 3px;
margin: 0;
padding-left: 20px;
}
.detailBlock p,
.detailBlock li,
.detailBlock a,
.notLinked {
overflow-wrap: anywhere;
white-space: pre-wrap;
}
.detailBlock a {
color: var(--link-color, #2563eb);
}
.notLinked {
color: var(--muted-foreground);
}
.primaryButton,
.secondaryButton {
appearance: none;
border: 1px solid var(--border);
border-radius: 6px;
padding: 7px 10px;
color: var(--foreground);
font: inherit;
font-size: 12px;
cursor: pointer;
}
.primaryButton {
flex: 0 0 auto;
background: var(--foreground);
color: var(--background);
}
.secondaryButton {
justify-self: start;
background: transparent;
}
.primaryButton:hover,
.secondaryButton:hover {
opacity: 0.82;
}
.report {
display: grid;
gap: 12px;
}
.evidenceImage {
display: block;
max-width: 100%;
max-height: 240px;
margin-bottom: 3px;
border: 1px solid var(--border);
border-radius: 6px;
}
.empty {
padding: 16px 4px;
color: var(--muted-foreground);
font-size: 13px;
}
.errorFallback {
display: grid;
gap: 8px;
justify-items: start;
}
.error {
display: grid;
gap: 5px;
padding: 12px;
border: 1px solid color-mix(in srgb, #dc2626 60%, var(--border));
border-radius: 8px;
color: var(--foreground);
background: color-mix(in srgb, #dc2626 8%, var(--background));
font-size: 13px;
overflow-wrap: anywhere;
}
@media (max-width: 900px) {
.summary {
display: grid;
}
.primaryButton {
justify-self: start;
}
}