Skip to content

Commit fc41922

Browse files
add compliance agents and YAML support for plot_info files
1 parent 6dd6ce9 commit fc41922

11 files changed

Lines changed: 269 additions & 11 deletions
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
name: 3m-gai-compliance-labeling
3+
description: This agent labels generated code to comply with 3M's generative AI conditions of use.
4+
argument-hint: You can start this agent by prompting 'label'.
5+
# tools: ['vscode', 'execute', 'read', 'agent', 'edit', 'search', 'web', 'todo'] # specify the tools this agent can use. If not set, all enabled tools are allowed.
6+
---
7+
8+
<!-- Tip: Use /create-agent in chat to generate content with agent assistance -->
9+
You are a CODE LABELING AGENT responsible for labeling generated code to ensure compliance with 3M's generative AI conditions of use.
10+
The generated-log.md file contains a record of all generated content added to the repository, including the file name, string of first and last lines, line numbers where the content was inserted, date, and AI model used. This allows for tracking of generated content and attribution.
11+
As you label generated content in the source code, mark the record in generated-log.md with the phrase 'labeled in source'.
12+
Generated Work must be clearly labeled (either for the entire library or sections of the software code) within the comments to distinguish Generated Work from human-authored sections. For example: 1) Code completely authored by Generative AI - “Section created by [ChatGPT, Github Co-Pilot, etc.], [date]” if fully authored by Generative AI, or 2) Code partially authored by Generative AI - “Draft code in section was created by [ChatGPT, Github Co-Pilot, etc.] and reviewed, edited, and revised by [3M human developer], [details on what was added to Generated Work], [date]”.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
name: 3m-gai-compliance-source-scan
3+
description: This agent performs a source code scan to comply with 3M's generative AI conditions of use.
4+
argument-hint: You can start this agent by prompting 'scan' or you can ask for a specific scanning tool if you have a preference. You can also specify the type of output you want, such as a detailed report or a summary of findings.
5+
# tools: ['vscode', 'execute', 'read', 'agent', 'edit', 'search', 'web', 'todo'] # specify the tools this agent can use. If not set, all enabled tools are allowed.
6+
---
7+
8+
<!-- Tip: Use /create-agent in chat to generate content with agent assistance -->
9+
You are a COMPLIANCE SOURCE SCAN AGENT responsible for performing a comprehensive source code scan to ensure compliance with 3M's generative AI conditions of use.
10+
You must install or check if installed the necessary tools to perform a source code scan (from vendors such as Blackduck, Whitesource, or Sonatype). This scan will identify any code security vulnerabilities, as well as ownership and attribution issues related to the Generated Work. The scan will also include a review of the security and license status of all referenced open-source libraries within the project.
11+
By default you will save your finding to a markdown file in the root of the repository named `compliance-scan-report.md` and also share the findings directly in the chat. The report should include a summary of findings, detailed information on any identified issues, and recommendations for remediation.

.github/copilot-instructions.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
## Compliance Enforcement
2+
3+
- For every copilot task in this repository, run the compliance workflow before finishing.
4+
- Treat compliance review as always-on, even when the user does not explicitly ask for it.
5+
- Whenever adding generated content to the repository add the first and last lines of the content to the generated-log.md file in the root directory. Label each entry with the file name, line numbers where the content was inserted, date, and AI model. This will allow for tracking of generated content and attribution.
6+
- generated-log.md contains a table. The column order is | Labeled in Source | Date | Model | File | Lines | First Line | Last Line |. The labeled in source column starts with 'no' and should be updated to 'yes' when the generated content is labeled in the source code with comments.
7+
8+
## When To Use Custom Agents
9+
10+
- Use the `3m-gai-compliance-source-scan` agent for full repository compliance scans, dependency/license review, or when the user asks about compliance. Only do this automatically before commits.
11+
- Use the `3m-gai-compliance-labeling` agent only if requested. Do not use it automatically, as it adds extra comments to the code which some users may find undesirable especiially during development.

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

77

8+
## [1.5.0] - 2026-04-11
9+
10+
### Added
11+
- ability to use yaml for plot_info files as well as json
12+
813
## [1.4.0] - 2025-12-29
914

1015
### Added

README.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
scatter plot all the things in all the folders automatically but only if there have been changes
33

44
## Description
5-
Plotme takes tabular data (e.g. excel) and outputs interactive scatter plots. It is a command line tool written in python. It uses json files to configure the plots. It is for technical and non-techncial folks.
5+
Plotme takes tabular data (e.g. excel) and outputs interactive scatter plots. It is a command line tool written in python. It uses json or yaml files to configure the plots. It is for technical and non-techncial folks.
66

77
## Features
88
* specify data_root using argument or current directory
99
* save the plot's configuration/definition with the data (plot_info.json)
1010
* finds plot_info files at any depth in the folder tree
11-
* validation plot_info.json using jsonschema
11+
* validation plot_info.json/yml/yaml using jsonschema
1212
* pass-through to plotly
1313
* scatter plot
1414
* `trace_mode` (markers or lines)
@@ -92,10 +92,9 @@ in this example
9292
0. sign exe and add to releases
9393
1. create better tests
9494
2. Hierarchical plot_info based on folder structure
95-
3. yml support
96-
4. pkl data file support
97-
5. 3D plots
98-
6. plot_info linter
95+
3. pkl data file support
96+
4. 3D plots
97+
5. plot_info linter
9998

10099
### Develop
101100
1. clone

compliance-scan-report.md

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
# Compliance Source Code Scan Report
2+
3+
**Project:** plotme
4+
**Version:** 1.4.0
5+
**Repository:** 3M-Cloud/vibedemo26-milo
6+
**Scan Date:** 2026-03-26
7+
**Scan Tools:** pip-audit 2.10.0, bandit 1.x, pip-licenses 5.5.1
8+
9+
---
10+
11+
## Executive Summary
12+
13+
| Category | Status | Finding Count |
14+
|----------|--------|---------------|
15+
| Source Code Security (Bandit) | ✅ PASS | 0 issues |
16+
| Dependency Vulnerabilities (pip-audit) | ⚠️ ACTION REQUIRED | 2 CVEs found |
17+
| License Compliance | ⚠️ REVIEW REQUIRED | 1 proprietary + 2 MPL-2.0 packages |
18+
| Open-Source Attribution | ✅ PASS | All deps identified |
19+
20+
---
21+
22+
## 1. Source Code Security Analysis
23+
24+
**Tool:** Bandit (static analysis)
25+
**Scope:** `plotme/` package (633 lines of code across 7 files)
26+
**Result:** **PASS – No security issues found**
27+
28+
| File | Lines of Code | Issues |
29+
|------|--------------|--------|
30+
| `plotme/__init__.py` | 3 | 0 |
31+
| `plotme/__main__.py` | 48 | 0 |
32+
| `plotme/helper.py` | 64 | 0 |
33+
| `plotme/load_data.py` | 223 | 0 |
34+
| `plotme/plotting.py` | 183 | 0 |
35+
| `plotme/read.py` | 9 | 0 |
36+
| `plotme/schema.py` | 103 | 0 |
37+
38+
No HIGH, MEDIUM, or LOW severity vulnerabilities detected (OWASP Top 10 categories checked: injection, insecure deserialization, use of known-vulnerable components, sensitive data exposure, etc.).
39+
40+
---
41+
42+
## 2. Dependency Vulnerability Scan
43+
44+
**Tool:** pip-audit 2.10.0 (backed by PyPI Advisory Database)
45+
**Result:** ⚠️ **2 known CVEs found — action required**
46+
47+
### CVE Findings
48+
49+
| Package | Version | CVE ID | GHSA | Fix Version | Severity | Description |
50+
|---------|---------|--------|------|-------------|----------|-------------|
51+
| **pip** | 25.3 | CVE-2026-1703 | GHSA-6vgw-5pg2-w6jp | 26.0 | MEDIUM | Path traversal during wheel archive extraction. Files may be extracted outside the installation directory. Only exploitable with a maliciously crafted wheel. |
52+
| **pygments** | 2.19.2 | CVE-2026-4539 | GHSA-5239-wwwm-4pmq | None available | LOW | Inefficient regex in `AdlLexer` (`pygments/lexers/archetype.py`) can cause ReDoS under local access conditions. |
53+
54+
> **Note:** `pygments` is an indirect/dev dependency (used by `rich` and other tooling). It is **not** a direct dependency of `plotme`.
55+
56+
> **Note:** `pip` itself is the package manager, not a runtime dependency of `plotme`.
57+
58+
### Recommendations
59+
60+
1. **pip (CVE-2026-1703):** Upgrade `pip` to version `26.0` or later.
61+
```
62+
pip install --upgrade pip
63+
```
64+
2. **pygments (CVE-2026-4539):** No fix version is currently available. Monitor the [pygments issue tracker](https://github.com/pygments/pygments) for a patch. Consider pinning to this version and adding a waiver with justification (local-only exploit, low severity).
65+
66+
### Skip Notice
67+
68+
`plotme` (1.4.0) itself was not found on PyPI and could not be audited against the PyPI advisory database. This is expected for an internal/proprietary package.
69+
70+
---
71+
72+
## 3. Open-Source Dependency Licenses
73+
74+
**Tool:** pip-licenses 5.5.1
75+
**Result:** ⚠️ **Review required for MPL-2.0 and proprietary license entries**
76+
77+
### License Summary
78+
79+
| License | Count | Notes |
80+
|---------|-------|-------|
81+
| MIT / MIT License | 30 | ✅ Permissive – generally acceptable |
82+
| Apache-2.0 / Apache Software License | 11 | ✅ Permissive – generally acceptable |
83+
| BSD License / BSD-2-Clause / BSD-3-Clause | 9 | ✅ Permissive – generally acceptable |
84+
| Mozilla Public License 2.0 (MPL 2.0) | 2 | ⚠️ Weak copyleft – file-level copyleft applies |
85+
| Python Software Foundation License | 1 | ✅ Permissive |
86+
| LicenseRef-Proprietary | 1 | ⚠️ plotme itself – internal project |
87+
88+
### MPL-2.0 Packages (Weak Copyleft)
89+
90+
| Package | Version | URL |
91+
|---------|---------|-----|
92+
| certifi | 2026.2.25 | https://github.com/certifi/python-certifi |
93+
| pathspec | 1.0.4 | N/A |
94+
95+
MPL-2.0 is file-level copyleft: modifications to MPL-licensed files must be released under MPL-2.0. Since `certifi` and `pathspec` are used as-is (unmodified), this does not impose redistribution obligations on `plotme`. **No immediate action required**, but document usage in your third-party notices file.
96+
97+
### Full Dependency License Table
98+
99+
| Name | Version | License | Author |
100+
|------|---------|---------|--------|
101+
| CacheControl | 0.14.4 | Apache-2.0 | Eric Larson et al. |
102+
| GitPython | 3.1.41 | BSD License | Sebastian Thiel, Michael Trier |
103+
| PyYAML | 6.0.3 | MIT License | Kirill Simonov |
104+
| Pygments | 2.19.2 | BSD License | Georg Brandl |
105+
| attrs | 26.1.0 | MIT | Hynek Schlawack |
106+
| boolean.py | 5.0 | BSD-2-Clause | Sebastian Kraemer |
107+
| certifi | 2026.2.25 | MPL-2.0 | Kenneth Reitz |
108+
| charset-normalizer | 3.4.6 | MIT | Ahmed R. TAHRI |
109+
| cyclonedx-python-lib | 11.7.0 | Apache-2.0 | Paul Horton |
110+
| defusedxml | 0.7.1 | PSF License | Christian Heimes |
111+
| dirhash | 0.5.0 | MIT | Anders Huss |
112+
| et_xmlfile | 2.0.0 | MIT License | See AUTHORS.txt |
113+
| filelock | 3.25.2 | MIT | (see project) |
114+
| gitdb | 4.0.12 | BSD License | Sebastian Thiel |
115+
| idna | 3.11 | BSD-3-Clause | Kim Davies |
116+
| iniconfig | 2.3.0 | MIT | Ronny Pfannschmidt et al. |
117+
| jsonschema | 4.26.0 | MIT | Julian Berman |
118+
| jsonschema-specifications | 2025.9.1 | MIT | Julian Berman |
119+
| license-expression | 30.4.4 | Apache-2.0 | nexB. Inc. and others |
120+
| markdown-it-py | 4.0.0 | MIT License | Chris Sewell |
121+
| mdurl | 0.1.2 | MIT License | Taneli Hukkinen |
122+
| msgpack | 1.1.2 | Apache-2.0 | Inada Naoki |
123+
| narwhals | 2.18.1 | MIT License | Marco Gorelli |
124+
| numpy | 2.4.3 | BSD-3-Clause + 0BSD + MIT + Zlib + CC0-1.0 | Travis E. Oliphant et al. |
125+
| openpyxl | 3.1.5 | MIT License | See AUTHORS |
126+
| packageurl-python | 0.17.6 | MIT License | the purl authors |
127+
| packaging | 26.0 | Apache-2.0 OR BSD-2-Clause | Donald Stufft |
128+
| pandas | 3.0.1 | BSD License | The Pandas Development Team |
129+
| pathspec | 1.0.4 | MPL-2.0 | Caleb P. Burns |
130+
| pip-api | 0.0.34 | Apache Software License | Dustin Ingram |
131+
| pip-requirements-parser | 32.0.1 | MIT | nexB. Inc. and others |
132+
| pip_audit | 2.10.0 | Apache Software License | Alex Cameron |
133+
| platformdirs | 4.9.4 | MIT | (see project) |
134+
| plotly | 6.6.0 | MIT License | Chris P |
135+
| plotme | 1.4.0 | Proprietary | Milo Oien-Rochat, Daniel Garcia |
136+
| pluggy | 1.6.0 | MIT License | Holger Krekel |
137+
| py-serializable | 2.1.0 | Apache Software License | Paul Horton |
138+
| pyparsing | 3.3.2 | MIT | Paul McGuire |
139+
| pytest | 9.0.2 | MIT | Holger Krekel et al. |
140+
| python-dateutil | 2.9.0.post0 | Apache + BSD | Gustavo Niemeyer |
141+
| referencing | 0.37.0 | MIT | Julian Berman |
142+
| requests | 2.33.0 | Apache Software License | Kenneth Reitz |
143+
| rich | 14.3.3 | MIT License | Will McGugan |
144+
| rpds-py | 0.30.0 | MIT | Julian Berman |
145+
| scandir | 1.10.0 | BSD License | Ben Hoyt |
146+
| scantree | 0.0.4 | MIT | Anders Huss |
147+
| six | 1.17.0 | MIT License | Benjamin Peterson |
148+
| smmap | 5.0.3 | BSD License | Sebastian Thiel |
149+
| sortedcontainers | 2.4.0 | Apache Software License | Grant Jenks |
150+
| tomli | 2.4.1 | MIT | Taneli Hukkinen |
151+
| tomli_w | 1.2.0 | MIT License | Taneli Hukkinen |
152+
| urllib3 | 2.6.3 | MIT | Andrey Petrov |
153+
154+
---
155+
156+
## 4. Project License & Attribution
157+
158+
- **Project License:** MIT License (Copyright © 2022 3M Company) — see `LICENSE`
159+
- **pyproject.toml declares:** `LicenseRef-Proprietary` (mismatch with the `LICENSE` file which contains MIT text)
160+
⚠️ **Recommendation:** Align the `license` field in `pyproject.toml` with the actual `LICENSE` file. Change `license = "LicenseRef-Proprietary"` to `license = {file = "LICENSE"}` or `license = "MIT"`.
161+
162+
---
163+
164+
## 5. Remediation Summary
165+
166+
| Priority | Action | Package | Details |Resolution|
167+
|----------|--------|---------|---------|------|
168+
| HIGH | Upgrade pip | pip 25.3 | Upgrade to ≥ 26.0 to fix CVE-2026-1703 path traversal | version not managed by plotme|
169+
| MEDIUM | Monitor / accept risk | pygments 2.19.2 | CVE-2026-4539 – no fix yet; low severity, local access only |version not managed by plotme|
170+
| LOW | Fix pyproject.toml | plotme | Align `license` field with actual MIT `LICENSE` file |fixed|
171+
| LOW | Document MPL-2.0 usage | certifi, pathspec | Add to third-party notices; no modification made, no redistribution obligation | none needed|
172+
173+
---
174+
*Report generated by GitHub Copilot Compliance Scan Agent on 2026-03-26.*

generated-log.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Generated Content Log
2+
3+
| Labeled in Source | Date | Model | File | Lines | First Line | Last Line |
4+
|-------------------|------|-------|------|-------|------------|-----------|
5+
| no | 2026-03-26 | Claude Sonnet 4.6 | plotme/plotting.py | 7 | `import yaml` | `import yaml` |
6+
| no | 2026-03-26 | Claude Sonnet 4.6 | plotme/plotting.py | 35-44 | ` plot_info_files = (` | ` )` |
7+
| no | 2026-03-26 | Claude Sonnet 4.6 | plotme/plotting.py | 67-72 | ` with open(file) as plot_info_file_handle:` | ` plot_info = json.load(plot_info_file_handle)` |
8+
| no | 2026-03-26 | Claude Sonnet 4.6 | tests/test_plotme.py | 7 | `import yaml` | `import yaml` |
9+
| no | 2026-03-26 | Claude Sonnet 4.6 | tests/test_plotme.py | 69-88 | `def test_yaml_plot_info():` | ` os.remove(data_file_name)` |
10+
| no | 2026-03-26 | Claude Sonnet 4.6 | pyproject.toml | 25 | ` 'pyyaml',` | ` 'pyyaml',` |

plotme/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import os
22

3-
__version__ = '1.4.0'
3+
__version__ = '1.5.0'
44

55
os.environ['PLOTME_VERSION'] = __version__

plotme/plotting.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import os
55
from pathlib import Path
66

7+
import yaml
8+
79
import plotly.graph_objects as go
810
import plotly.io as pio
911
from dirhash import dirhash
@@ -32,7 +34,11 @@ def plot_all(args_dict={}):
3234
plot_info_file = args_dict.get('plot_info_file', plot_info_id)
3335

3436
data_root = Path(args_dict.get('data_root', os.getcwd()))
35-
plot_info_files = list(data_root.glob(f"**/*{plot_info_file}.json"))
37+
plot_info_files = (
38+
list(data_root.glob(f"**/*{plot_info_file}.json")) +
39+
list(data_root.glob(f"**/*{plot_info_file}.yaml")) +
40+
list(data_root.glob(f"**/*{plot_info_file}.yml"))
41+
)
3642

3743
# save template plot_info.json
3844
if len(plot_info_files) == 0 or args_dict.get('template'):
@@ -65,8 +71,11 @@ def plot_all(args_dict={}):
6571
logging.info(f"no changes detected, skipping {file}")
6672
else:
6773
logging.info(f'loading plot settings from {file}')
68-
with open(file) as json_file:
69-
plot_info = json.load(json_file)
74+
with open(file) as plot_info_file_handle:
75+
if file.suffix.lower() in ('.yaml', '.yml'):
76+
plot_info = yaml.safe_load(plot_info_file_handle)
77+
else:
78+
plot_info = json.load(plot_info_file_handle)
7079
validate(instance=plot_info, schema=schema)
7180
plot_info['plot_dir'] = dir_path
7281
plot_info['plot_info_file'] = file

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ authors = [
1313
{name = "Daniel Garcia", email = "dgarcia7654@users.noreply.github.com"}
1414
]
1515
requires-python = ">=3.8"
16-
license = "LicenseRef-Proprietary"
16+
license = {file = "LICENSE"}
1717
keywords = ["plotting", "data", "plotly", "cli"]
1818
dependencies = [
1919
'dirhash',

0 commit comments

Comments
 (0)