aienvmp 0.1.17 → 0.1.18
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.
- package/CHANGELOG.md +6 -0
- package/README.md +1 -1
- package/package.json +1 -1
- package/src/commands/dash.js +13 -1
- package/src/render.js +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.18
|
|
4
|
+
|
|
5
|
+
- Added a dashboard remediation steps card backed by `.aienvmp/plan.json`.
|
|
6
|
+
- Kept dashboard remediation details bounded to package, severity, fix version, and advisory references.
|
|
7
|
+
- Improved human visibility for AI-generated read-only security plans.
|
|
8
|
+
|
|
3
9
|
## 0.1.17
|
|
4
10
|
|
|
5
11
|
- Added bounded security remediation steps to `aienvmp plan`.
|
package/README.md
CHANGED
|
@@ -38,7 +38,7 @@ AIENV.md
|
|
|
38
38
|
.aienvmp/timeline.jsonl
|
|
39
39
|
.aienvmp/plan.json
|
|
40
40
|
.aienvmp/plan.md
|
|
41
|
-
.aienvmp/dashboard.html
|
|
41
|
+
.aienvmp/dashboard.html # includes plan and remediation cards
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
Trust states are machine-readable: `observed`, `planned`, `changed`, `review`, `verified`, `stale`.
|
package/package.json
CHANGED
package/src/commands/dash.js
CHANGED
|
@@ -18,7 +18,8 @@ export async function dashWorkspace(args) {
|
|
|
18
18
|
const policy = await loadPolicy(dir);
|
|
19
19
|
const warnings = [...diagnose(manifest, { timeline, intents }), ...policyWarnings(manifest, policy)];
|
|
20
20
|
const planArtifacts = await detectedPlanArtifacts(dir);
|
|
21
|
-
const
|
|
21
|
+
const planRemediation = await detectedPlanRemediation(dir);
|
|
22
|
+
const html = renderDashboard({ ...manifest, recommendedActions: recommendedActions(manifest, { warnings, intents }), planArtifacts, planRemediation }, timeline, warnings, intents, policy);
|
|
22
23
|
const out = dashboardPath(dir);
|
|
23
24
|
await fs.mkdir(path.dirname(out), { recursive: true });
|
|
24
25
|
await fs.writeFile(out, html, "utf8");
|
|
@@ -36,6 +37,17 @@ async function detectedPlanArtifacts(dir) {
|
|
|
36
37
|
};
|
|
37
38
|
}
|
|
38
39
|
|
|
40
|
+
async function detectedPlanRemediation(dir) {
|
|
41
|
+
const plan = await readJson(planJsonPath(dir), {});
|
|
42
|
+
return (plan.remediationSteps || []).slice(0, 5).map((item) => ({
|
|
43
|
+
package: item.package || "unknown",
|
|
44
|
+
severity: item.severity || "unknown",
|
|
45
|
+
fixVersions: Array.isArray(item.fixVersions) ? item.fixVersions.slice(0, 3) : [],
|
|
46
|
+
fixAvailable: item.fixAvailable === true,
|
|
47
|
+
advisories: Array.isArray(item.advisories) ? item.advisories.map((advisory) => advisory.id || advisory.title).filter(Boolean).slice(0, 2) : []
|
|
48
|
+
}));
|
|
49
|
+
}
|
|
50
|
+
|
|
39
51
|
function openFile(file) {
|
|
40
52
|
if (process.platform === "win32") {
|
|
41
53
|
execFile("cmd", ["/c", "start", "", file], { windowsHide: true });
|
package/src/render.js
CHANGED
|
@@ -278,6 +278,10 @@ const actions=manifest.recommendedActions||[];
|
|
|
278
278
|
const actionsHtml=actions.length?'<div class="timeline">'+actions.slice(0,6).map(a=>\`<div class="event"><time>\${esc(a.priority)}</time><div><b>\${esc(a.category)}</b> \${esc(a.summary)}\${a.command?\`<div class="path">\${esc(a.command)}</div>\`:''}</div></div>\`).join('')+'</div>':'<div class="okline">No recommended actions. Continue project-local work.</div>';
|
|
279
279
|
const plan=manifest.planArtifacts||{};
|
|
280
280
|
const planHtml=plan.markdown||plan.json?\`<table><tr><th>Markdown</th><td>\${plan.markdown?'<a href="plan.md">plan.md</a>':'not written'}</td></tr><tr><th>JSON</th><td>\${plan.json?'<a href="plan.json">plan.json</a>':'not written'}</td></tr></table>\`:'<div class="okline">No plan artifacts yet. Run <code>aienvmp plan --write</code>.</div>';
|
|
281
|
+
const remediation=manifest.planRemediation||[];
|
|
282
|
+
const remediationFix=r=>r.fixVersions?.length?\`fix \${r.fixVersions.join(', ')}\`:(r.fixAvailable?'fix available':'review required');
|
|
283
|
+
const remediationRefs=r=>r.advisories?.length?\` - \${r.advisories.join(', ')}\`:'';
|
|
284
|
+
const remediationHtml=remediation.length?'<div class="timeline">'+remediation.map(r=>\`<div class="event"><time>\${esc(r.severity)}</time><div><b>\${esc(r.package)}</b> \${esc(remediationFix(r))}\${esc(remediationRefs(r))}</div></div>\`).join('')+'</div>':'<div class="okline">No remediation steps in the current plan.</div>';
|
|
281
285
|
const card=(title,badge,body)=>\`<section class="card"><div class="card-head"><h2>\${title}</h2>\${badge||''}</div>\${body}</section>\`;
|
|
282
286
|
const reviewRequired=warnings.length>0||intents.length>0;
|
|
283
287
|
const recentChanges=timeline.slice(-8).length;
|
|
@@ -321,6 +325,8 @@ document.getElementById('app').innerHTML=\`
|
|
|
321
325
|
<div style="height:14px"></div>
|
|
322
326
|
\${card('AI Plan Artifacts',plan.markdown||plan.json?'<span class="pill">written</span>':'<span class="pill off">not written</span>',planHtml)}
|
|
323
327
|
<div style="height:14px"></div>
|
|
328
|
+
\${card('Remediation Steps',remediation.length?'<span class="pill warn">'+remediation.length+' items</span>':'<span class="pill off">none</span>',remediationHtml)}
|
|
329
|
+
<div style="height:14px"></div>
|
|
324
330
|
\${card('Environment Health',warnings.length?'<span class="pill warn">attention</span>':'<span class="pill">clear</span>',warnHtml)}
|
|
325
331
|
<div style="height:14px"></div>
|
|
326
332
|
\${card('Version Policy','<span class="pill">'+entries(policy).length+' rules</span>',policyHtml)}
|