aienvmp 0.1.16 → 0.1.17

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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.17
4
+
5
+ - Added bounded security remediation steps to `aienvmp plan`.
6
+ - Included package fix versions and advisory references in plan JSON and markdown output.
7
+ - Kept remediation output read-only and review-oriented.
8
+
3
9
  ## 0.1.16
4
10
 
5
11
  - Added scoped strict checks with `doctor --strict security|policy|coordination|all`.
package/README.md CHANGED
@@ -59,7 +59,7 @@ npx aienvmp snippet agents
59
59
  aienvmp sync # update env map, light SBOM, ledger, dashboard
60
60
  aienvmp context # AI preflight brief
61
61
  aienvmp context --json # machine-readable AI decision context + recommended actions
62
- aienvmp plan # read-only AI action plan, no automatic fixes
62
+ aienvmp plan # read-only AI action plan with remediation steps
63
63
  aienvmp handoff # next-agent handoff summary + recommended actions
64
64
  aienvmp intent # record a planned env change
65
65
  aienvmp record # record what changed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aienvmp",
3
- "version": "0.1.16",
3
+ "version": "0.1.17",
4
4
  "description": "AI-first environment maps and lightweight runtime SBOMs for shared development machines.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -56,6 +56,7 @@ export function buildPlan(manifest, warnings = [], intents = [], policy = {}) {
56
56
  summary: manifest.security?.summary || { total: 0, critical: 0, high: 0, moderate: 0, low: 0, info: 0 },
57
57
  topPackages: manifest.security?.topPackages || []
58
58
  },
59
+ remediationSteps: remediationSteps(manifest.security),
59
60
  notes: [
60
61
  "This plan is read-only.",
61
62
  "Ask the user before global runtime, package manager, Docker, or global package changes.",
@@ -64,6 +65,35 @@ export function buildPlan(manifest, warnings = [], intents = [], policy = {}) {
64
65
  };
65
66
  }
66
67
 
68
+ function remediationSteps(security = {}) {
69
+ if (!security.enabled) return [];
70
+ return (security.topPackages || []).slice(0, 8).map((pkg) => {
71
+ const fixVersions = Array.isArray(pkg.fixVersions) ? pkg.fixVersions.slice(0, 5) : [];
72
+ const advisories = Array.isArray(pkg.advisories)
73
+ ? pkg.advisories.map((item) => ({
74
+ id: item.id || "",
75
+ title: item.title || "",
76
+ url: item.url || "",
77
+ severity: item.severity || pkg.severity || "unknown"
78
+ })).slice(0, 5)
79
+ : [];
80
+ return {
81
+ package: pkg.name,
82
+ scanner: pkg.scanner || "unknown",
83
+ severity: pkg.severity || "unknown",
84
+ fixAvailable: pkg.fixAvailable === true,
85
+ fixVersions,
86
+ advisories,
87
+ steps: [
88
+ "Review the package changelog and advisory details.",
89
+ fixVersions.length ? `Prefer an upgrade path to ${fixVersions.join(", ")} if compatible.` : "Identify a compatible patched version before changing dependencies.",
90
+ "Run project tests after dependency changes.",
91
+ "Record the environment or dependency change with aienvmp record."
92
+ ]
93
+ };
94
+ });
95
+ }
96
+
67
97
  function reviewGates(warnings, intents, security = {}) {
68
98
  const gates = [];
69
99
  if (warnings.length) gates.push("Review warnings before changing the environment.");
package/src/render.js CHANGED
@@ -182,6 +182,9 @@ export function renderPlan(plan) {
182
182
  "Review gates:",
183
183
  ...plan.reviewGates.map((item) => `- ${item}`),
184
184
  "",
185
+ "Remediation steps:",
186
+ ...(plan.remediationSteps?.length ? plan.remediationSteps.slice(0, 5).flatMap(remediationLines) : ["- none"]),
187
+ "",
185
188
  "Warnings:",
186
189
  ...(plan.warnings.length ? plan.warnings.map((warning) => `- [${warning.code}] ${warning.message}`) : ["- none"]),
187
190
  ""
@@ -189,6 +192,15 @@ export function renderPlan(plan) {
189
192
  return lines.join("\n");
190
193
  }
191
194
 
195
+ function remediationLines(item) {
196
+ const fix = item.fixVersions?.length ? `fix ${item.fixVersions.join(", ")}` : item.fixAvailable ? "fix available" : "review required";
197
+ const advisories = (item.advisories || []).map((advisory) => advisory.id || advisory.title).filter(Boolean).slice(0, 2);
198
+ return [
199
+ `- ${item.package}: ${item.severity}; ${fix}${advisories.length ? `; advisories ${advisories.join(", ")}` : ""}`,
200
+ ...item.steps.slice(0, 4).map((step) => ` - ${step}`)
201
+ ];
202
+ }
203
+
192
204
  export function renderDashboard(manifest, timeline = [], warnings = [], intents = [], policy = {}) {
193
205
  const data = JSON.stringify({ manifest, timeline, warnings, intents, policy });
194
206
  return `<!doctype html>