aienvmp 0.1.18 → 0.1.19

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.19
4
+
5
+ - Added runtime, package manager, Docker, and coordination environment steps to `aienvmp plan`.
6
+ - Kept environment plans read-only and ask-first for global changes.
7
+ - Improved AI guidance for resolving version drift and multi-agent coordination warnings.
8
+
3
9
  ## 0.1.18
4
10
 
5
11
  - Added a dashboard remediation steps card backed by `.aienvmp/plan.json`.
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 with remediation steps
62
+ aienvmp plan # read-only AI action plan for drift and remediation
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.18",
3
+ "version": "0.1.19",
4
4
  "description": "AI-first environment maps and lightweight runtime SBOMs for shared development machines.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -57,6 +57,7 @@ export function buildPlan(manifest, warnings = [], intents = [], policy = {}) {
57
57
  topPackages: manifest.security?.topPackages || []
58
58
  },
59
59
  remediationSteps: remediationSteps(manifest.security),
60
+ environmentSteps: environmentSteps(warnings),
60
61
  notes: [
61
62
  "This plan is read-only.",
62
63
  "Ask the user before global runtime, package manager, Docker, or global package changes.",
@@ -65,6 +66,81 @@ export function buildPlan(manifest, warnings = [], intents = [], policy = {}) {
65
66
  };
66
67
  }
67
68
 
69
+ function environmentSteps(warnings = []) {
70
+ return warnings
71
+ .filter((warning) => warning.code !== "security-vulnerabilities")
72
+ .slice(0, 8)
73
+ .map((warning) => ({
74
+ code: warning.code,
75
+ category: environmentCategory(warning.code),
76
+ summary: warning.message,
77
+ steps: environmentStepLines(warning.code)
78
+ }));
79
+ }
80
+
81
+ function environmentCategory(code = "") {
82
+ if (["conflicting-open-intents", "stale-open-intent", "handoff-stale"].includes(code)) return "coordination";
83
+ if (code.includes("docker")) return "container";
84
+ if (code.includes("lockfile") || code.includes("package-manager")) return "package-manager";
85
+ if (code.includes("node") || code.includes("python") || code.includes("version") || code.includes("runtime")) return "runtime";
86
+ return "environment";
87
+ }
88
+
89
+ function environmentStepLines(code = "") {
90
+ if (code === "node-version-mismatch") return [
91
+ "Read .nvmrc and the detected Node version before changing tools.",
92
+ "Prefer project-local version managers such as nvm, mise, or asdf.",
93
+ "Ask before changing global Node or npm installations.",
94
+ "Run aienvmp sync and record the change after alignment."
95
+ ];
96
+ if (code === "python-version-mismatch") return [
97
+ "Read .python-version and the detected Python version before changing tools.",
98
+ "Prefer project-local virtual environments or version managers.",
99
+ "Ask before changing global Python installations.",
100
+ "Run aienvmp sync and record the change after alignment."
101
+ ];
102
+ if (code === "mixed-node-lockfiles" || code === "package-manager-policy-mismatch") return [
103
+ "Identify the intended package manager from project policy and lockfiles.",
104
+ "Do not delete lockfiles without user approval.",
105
+ "Use one package manager for dependency changes.",
106
+ "Record the chosen package manager policy if it changes."
107
+ ];
108
+ if (code === "python-missing") return [
109
+ "Confirm whether the Python project is active.",
110
+ "Prefer project-local Python setup before global installation.",
111
+ "Ask before installing a global Python runtime.",
112
+ "Run aienvmp sync after setup."
113
+ ];
114
+ if (code === "docker-missing") return [
115
+ "Confirm whether Docker is required for the current task.",
116
+ "Do not change Docker daemon or context without user approval.",
117
+ "Document fallback commands if Docker is unavailable.",
118
+ "Run aienvmp sync after Docker availability changes."
119
+ ];
120
+ if (code === "manifest-stale") return [
121
+ "Run aienvmp sync before environment changes.",
122
+ "Review context again after refresh."
123
+ ];
124
+ if (code === "conflicting-open-intents") return [
125
+ "Review open intents before changing the environment.",
126
+ "Coordinate with the user or other agent.",
127
+ "Resolve stale or superseded intents before proceeding."
128
+ ];
129
+ if (code === "stale-open-intent") return [
130
+ "Confirm whether the old intent is still valid.",
131
+ "Resolve or renew the intent before changing the environment."
132
+ ];
133
+ if (code === "handoff-stale") return [
134
+ "Run aienvmp handoff --record --actor agent:id before the next AI continues.",
135
+ "Review recent changes before new environment work."
136
+ ];
137
+ return [
138
+ "Review the warning before changing environment state.",
139
+ "Ask before global environment changes.",
140
+ "Run aienvmp sync after any accepted change."
141
+ ];
142
+ }
143
+
68
144
  function remediationSteps(security = {}) {
69
145
  if (!security.enabled) return [];
70
146
  return (security.topPackages || []).slice(0, 8).map((pkg) => {
package/src/render.js CHANGED
@@ -185,6 +185,9 @@ export function renderPlan(plan) {
185
185
  "Remediation steps:",
186
186
  ...(plan.remediationSteps?.length ? plan.remediationSteps.slice(0, 5).flatMap(remediationLines) : ["- none"]),
187
187
  "",
188
+ "Environment steps:",
189
+ ...(plan.environmentSteps?.length ? plan.environmentSteps.slice(0, 5).flatMap(environmentLines) : ["- none"]),
190
+ "",
188
191
  "Warnings:",
189
192
  ...(plan.warnings.length ? plan.warnings.map((warning) => `- [${warning.code}] ${warning.message}`) : ["- none"]),
190
193
  ""
@@ -192,6 +195,13 @@ export function renderPlan(plan) {
192
195
  return lines.join("\n");
193
196
  }
194
197
 
198
+ function environmentLines(item) {
199
+ return [
200
+ `- ${item.category}: ${item.summary}`,
201
+ ...item.steps.slice(0, 4).map((step) => ` - ${step}`)
202
+ ];
203
+ }
204
+
195
205
  function remediationLines(item) {
196
206
  const fix = item.fixVersions?.length ? `fix ${item.fixVersions.join(", ")}` : item.fixAvailable ? "fix available" : "review required";
197
207
  const advisories = (item.advisories || []).map((advisory) => advisory.id || advisory.title).filter(Boolean).slice(0, 2);