aienvmp 0.1.2 → 0.1.4

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/BUGFIXES.md ADDED
@@ -0,0 +1,38 @@
1
+ # Bugfix Log
2
+
3
+ Short record of bugs, fixes, and follow-up checks.
4
+
5
+ ## 2026-07-08
6
+
7
+ ### CLI version was hardcoded
8
+
9
+ - Issue: `npm run smoke` printed `0.1.0` after the package version changed.
10
+ - Fix: CLI now reads the version from `package.json`.
11
+ - Verification: `npm run smoke` prints the package version.
12
+
13
+ ### AGENTS.md default generation conflicted with product focus
14
+
15
+ - Issue: default agent instruction file generation made `aienvmp` look like an AGENTS.md generator.
16
+ - Fix: `sync` now focuses on `AIENV.md`, manifest, intent log, timeline, and dashboard. Agent instruction integration is explicit through `aienvmp snippet`.
17
+ - Verification: `node --test` confirms `sync` does not create `AGENTS.md` by default and `snippet --write` only updates the marker block.
18
+
19
+ ### npm publish metadata appeared stale
20
+
21
+ - Issue: npm publish returned success for `0.1.2`, but `npm view aienvmp version` briefly returned `0.1.1`.
22
+ - Fix: verified with `npm view aienvmp versions --json` and `npm dist-tag ls aienvmp`; registry later reported `0.1.2`.
23
+ - Verification: `npm view aienvmp version` returns `0.1.2`.
24
+
25
+ ### macOS SSH PATH did not expose Node/npm
26
+
27
+ - Issue: remote macOS non-interactive SSH command did not find `node` or `npm`.
28
+ - Fix: test command used `/bin/zsh -lc` to load login shell PATH.
29
+ - Verification: remote test detected Node `v25.3.0`, npm `11.11.0`, and completed `aienvmp sync`.
30
+
31
+ ## Template
32
+
33
+ ### Title
34
+
35
+ - Issue:
36
+ - Fix:
37
+ - Verification:
38
+ - Follow-up:
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.4
4
+
5
+ - Added `aienvmp handoff` for next-agent environment handoff summaries.
6
+ - Added an AI Handoff card to the dashboard.
7
+ - Added handoff test coverage.
8
+
9
+ ## 0.1.3
10
+
11
+ - Strengthened the dashboard audit summary with AI decision, open intents, warnings, and recent changes.
12
+ - Added dashboard render coverage for the audit summary surface.
13
+
3
14
  ## 0.1.2
4
15
 
5
16
  - Added `aienvmp sync` as the simple one-step command for init, scan, `AIENV.md`, manifest, ledger, and dashboard generation.
@@ -8,6 +19,7 @@
8
19
  - Added machine-readable sync/context improvements for AI and CI integrations.
9
20
  - Simplified README for faster first-time understanding.
10
21
  - Kept AGENTS.md, CLAUDE.md, and GEMINI.md integration explicit through `aienvmp snippet`.
22
+ - Added troubleshooting and bugfix logs for operational issue tracking.
11
23
 
12
24
  ## 0.1.1
13
25
 
package/README.md CHANGED
@@ -48,6 +48,7 @@ npx aienvmp snippet agents
48
48
  aienvmp sync # update env map, light SBOM, ledger, dashboard
49
49
  aienvmp context # AI preflight brief
50
50
  aienvmp context --json # machine-readable AI decision context
51
+ aienvmp handoff # next-agent handoff summary
51
52
  aienvmp intent # record a planned env change
52
53
  aienvmp record # record what changed
53
54
  aienvmp doctor --ci # strict CI check
@@ -70,6 +71,6 @@ npm pack --dry-run
70
71
 
71
72
  ## Links
72
73
 
73
- [Roadmap](ROADMAP.md) / [Security](SECURITY.md) / [Contributing](CONTRIBUTING.md)
74
+ [Roadmap](ROADMAP.md) / [Security](SECURITY.md) / [Troubleshooting](TROUBLESHOOTING.md) / [Bugfix Log](BUGFIXES.md) / [Contributing](CONTRIBUTING.md)
74
75
 
75
76
  Apache-2.0
@@ -0,0 +1,103 @@
1
+ # Troubleshooting
2
+
3
+ Known operational issues and quick fixes for `aienvmp`.
4
+
5
+ ## npm publish succeeds but `npm view` still shows the old version
6
+
7
+ Symptom:
8
+
9
+ ```text
10
+ npm publish
11
+ + aienvmp@0.1.2
12
+ npm view aienvmp version
13
+ 0.1.1
14
+ ```
15
+
16
+ Cause:
17
+
18
+ - npm registry metadata can lag briefly after publish.
19
+
20
+ Check:
21
+
22
+ ```bash
23
+ npm view aienvmp versions --json
24
+ npm dist-tag ls aienvmp
25
+ ```
26
+
27
+ Fix:
28
+
29
+ - Wait briefly and re-check `npm view aienvmp version`.
30
+
31
+ ## Windows `npm exec --package ... -- aienvmp --help` cannot find the command
32
+
33
+ Symptom:
34
+
35
+ ```text
36
+ 'aienvmp' is not recognized as an internal or external command
37
+ ```
38
+
39
+ Notes:
40
+
41
+ - The package bin metadata can still be valid.
42
+ - A direct temporary install creates the expected `.bin/aienvmp.cmd` shim.
43
+
44
+ Check:
45
+
46
+ ```bash
47
+ npm view aienvmp bin --json
48
+ npm install aienvmp@latest --prefix ./tmp-aienvmp-check
49
+ ```
50
+
51
+ Workaround:
52
+
53
+ ```bash
54
+ npx aienvmp@latest --version
55
+ ```
56
+
57
+ or install first:
58
+
59
+ ```bash
60
+ npm install -g aienvmp
61
+ aienvmp --version
62
+ ```
63
+
64
+ ## macOS SSH session cannot find `node` or `npm`
65
+
66
+ Symptom:
67
+
68
+ ```text
69
+ command -v node
70
+ # empty in non-interactive SSH command
71
+ ```
72
+
73
+ Cause:
74
+
75
+ - Node may be configured only in the login shell environment.
76
+
77
+ Fix:
78
+
79
+ ```bash
80
+ /bin/zsh -lc 'node --version && npm --version'
81
+ ```
82
+
83
+ For automation, make sure the shell PATH includes the Node/npm location.
84
+
85
+ ## Missing manifest
86
+
87
+ Symptom:
88
+
89
+ ```text
90
+ aienvmp: missing manifest; run `aienvmp sync` first
91
+ ```
92
+
93
+ Fix:
94
+
95
+ ```bash
96
+ npx aienvmp sync
97
+ ```
98
+
99
+ Then retry:
100
+
101
+ ```bash
102
+ npx aienvmp context
103
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aienvmp",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "AI-first environment maps and lightweight runtime SBOMs for shared development machines.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -20,8 +20,10 @@
20
20
  "README.md",
21
21
  "LICENSE",
22
22
  "CHANGELOG.md",
23
+ "BUGFIXES.md",
23
24
  "CONTRIBUTING.md",
24
25
  "SECURITY.md",
26
+ "TROUBLESHOOTING.md",
25
27
  "ROADMAP.md",
26
28
  "action.yml",
27
29
  "examples",
package/src/cli.js CHANGED
@@ -10,6 +10,7 @@ import { intentWorkspace } from "./commands/intent.js";
10
10
  import { resolveWorkspace } from "./commands/resolve.js";
11
11
  import { syncWorkspace } from "./commands/sync.js";
12
12
  import { snippetWorkspace } from "./commands/snippet.js";
13
+ import { handoffWorkspace } from "./commands/handoff.js";
13
14
  import { readFileSync } from "node:fs";
14
15
 
15
16
  const commands = new Map([
@@ -24,7 +25,8 @@ const commands = new Map([
24
25
  ["intent", intentWorkspace],
25
26
  ["resolve", resolveWorkspace],
26
27
  ["sync", syncWorkspace],
27
- ["snippet", snippetWorkspace]
28
+ ["snippet", snippetWorkspace],
29
+ ["handoff", handoffWorkspace]
28
30
  ]);
29
31
 
30
32
  const version = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")).version;
@@ -74,10 +76,12 @@ function printUsage() {
74
76
  Usage:
75
77
  aienvmp sync [--dir .] [--json] [--quiet]
76
78
  aienvmp context [--dir .] [--json]
79
+ aienvmp handoff [--dir .] [--json]
77
80
 
78
81
  Common:
79
82
  aienvmp sync update AIENV.md, manifest, ledger, intents, and dashboard
80
83
  aienvmp context print the AI preflight brief
84
+ aienvmp handoff print the next-agent handoff summary
81
85
  aienvmp snippet print an AGENTS.md pointer snippet
82
86
  aienvmp dash regenerate/open the lightweight dashboard
83
87
 
@@ -0,0 +1,55 @@
1
+ import { diagnose } from "../doctor.js";
2
+ import { readJson } from "../fsutil.js";
3
+ import { loadPolicy, policyWarnings } from "../policy.js";
4
+ import { intentsPath, manifestPath, timelinePath, workspaceDir } from "../paths.js";
5
+ import { renderHandoff } from "../render.js";
6
+ import { openIntents, readJsonl, readTimeline } from "../timeline.js";
7
+
8
+ export async function handoffWorkspace(args) {
9
+ const dir = workspaceDir(args);
10
+ const manifest = await readJson(manifestPath(dir));
11
+ if (!manifest) throw new Error("missing manifest; run `aienvmp sync` first");
12
+ const timeline = await readTimeline(timelinePath(dir));
13
+ const intents = openIntents(await readJsonl(intentsPath(dir)));
14
+ const policy = await loadPolicy(dir);
15
+ const warnings = [...diagnose(manifest), ...policyWarnings(manifest, policy)];
16
+ const handoff = buildHandoff(manifest, timeline, warnings, intents, policy);
17
+
18
+ if (args.json) {
19
+ console.log(JSON.stringify(handoff, null, 2));
20
+ } else {
21
+ console.log(renderHandoff(handoff));
22
+ }
23
+ return handoff;
24
+ }
25
+
26
+ export function buildHandoff(manifest, timeline = [], warnings = [], intents = [], policy = {}) {
27
+ const reviewRequired = warnings.length > 0 || intents.length > 0;
28
+ return {
29
+ status: reviewRequired ? "review-required" : "clear",
30
+ workspace: manifest.workspace,
31
+ safeRuntime: {
32
+ node: manifest.runtimes?.node || "not detected",
33
+ python: manifest.runtimes?.python || manifest.runtimes?.python3 || "not detected",
34
+ docker: manifest.containers?.docker ? "available" : "not detected"
35
+ },
36
+ policy: {
37
+ node: policy.node || "not set",
38
+ python: policy.python || "not set",
39
+ packageManager: policy.packageManager || "not set",
40
+ runtimeChanges: policy.runtimeChanges || "ask-first",
41
+ globalInstalls: policy.globalInstalls || "ask-first"
42
+ },
43
+ openIntents: intents.slice(-5).reverse(),
44
+ warnings,
45
+ recentChanges: timeline.slice(-5).reverse(),
46
+ mustNotDo: [
47
+ "do not change global runtimes without user approval",
48
+ "do not install or remove global package managers without user approval",
49
+ "do not change Docker daemon/context assumptions without user approval"
50
+ ],
51
+ recommendedNext: reviewRequired
52
+ ? "review warnings and open intents before environment changes"
53
+ : "continue with project-local work; record intent before environment changes"
54
+ };
55
+ }
package/src/render.js CHANGED
@@ -111,6 +111,36 @@ export function renderContext(manifest, timeline = [], warnings = [], intents =
111
111
  ].join("\n");
112
112
  }
113
113
 
114
+ export function renderHandoff(handoff) {
115
+ const lines = [
116
+ "# AI Handoff",
117
+ "",
118
+ `Status: ${handoff.status}`,
119
+ `Workspace: ${handoff.workspace?.path || "unknown"}`,
120
+ "",
121
+ "Safe runtime:",
122
+ `- Node: ${handoff.safeRuntime.node}`,
123
+ `- Python: ${handoff.safeRuntime.python}`,
124
+ `- Docker: ${handoff.safeRuntime.docker}`,
125
+ "",
126
+ "Open intents:",
127
+ ...(handoff.openIntents.length ? handoff.openIntents.map((i) => `- ${i.actor}: ${i.action}${i.target ? ` (${i.target})` : ""}`) : ["- none"]),
128
+ "",
129
+ "Warnings:",
130
+ ...(handoff.warnings.length ? handoff.warnings.map((w) => `- ${w.message}`) : ["- none"]),
131
+ "",
132
+ "Recent changes:",
133
+ ...(handoff.recentChanges.length ? handoff.recentChanges.map((t) => `- ${formatTimeline(t)}`) : ["- none"]),
134
+ "",
135
+ "Must not do:",
136
+ ...handoff.mustNotDo.map((item) => `- ${item}`),
137
+ "",
138
+ `Recommended next: ${handoff.recommendedNext}`,
139
+ ""
140
+ ];
141
+ return lines.join("\n");
142
+ }
143
+
114
144
  export function renderDashboard(manifest, timeline = [], warnings = [], intents = [], policy = {}) {
115
145
  const data = JSON.stringify({ manifest, timeline, warnings, intents, policy });
116
146
  return `<!doctype html>
@@ -131,6 +161,13 @@ h1,h2,h3,p{margin:0}h1{font-size:clamp(28px,4vw,46px);line-height:1.02;margin-to
131
161
  .sub{color:var(--muted);margin-top:12px;max-width:680px;line-height:1.55}
132
162
  .stamp{min-width:220px;border:1px solid var(--line2);background:#091310;border-radius:8px;padding:14px}
133
163
  .stamp b{display:block;color:var(--green);font-size:24px;margin-bottom:3px}.stamp span{display:block;color:var(--muted);font-size:12px;overflow-wrap:anywhere}
164
+ .audit{display:grid;grid-template-columns:1.2fr repeat(3,minmax(0,.8fr));gap:12px;margin:14px 0}
165
+ .audit-item{border:1px solid var(--line);background:rgba(13,24,21,.92);border-radius:8px;padding:14px;min-width:0}
166
+ .audit-item.primary{background:linear-gradient(135deg,rgba(19,61,42,.88),rgba(9,19,16,.95))}
167
+ .audit-item.review{background:linear-gradient(135deg,rgba(81,53,17,.88),rgba(9,19,16,.95));border-color:rgba(244,191,95,.42)}
168
+ .audit-k{color:var(--muted);font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.08em}
169
+ .audit-v{margin-top:7px;font-size:20px;font-weight:800;color:var(--text);overflow-wrap:anywhere}
170
+ .audit-hint{margin-top:6px;color:var(--muted);font-size:12px;line-height:1.4}
134
171
  .metrics{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin:14px 0 18px}
135
172
  .metric,.card{border:1px solid var(--line);background:rgba(13,24,21,.9);border-radius:8px}
136
173
  .metric{padding:14px}.metric .num{font-size:28px;font-weight:800;color:var(--green);line-height:1}.metric .label{margin-top:7px;color:var(--muted);font-size:12px}
@@ -147,7 +184,9 @@ code{color:var(--code);background:#0a2017;border:1px solid #17462f;padding:2px 6
147
184
  .timeline{display:grid;gap:10px}.event{display:grid;grid-template-columns:108px 1fr;gap:12px;border-top:1px solid var(--line2);padding-top:10px}.event time{color:var(--muted);font-size:12px}.event b{color:var(--green)}
148
185
  .path{font-family:ui-monospace,SFMono-Regular,Consolas,monospace;color:var(--muted);font-size:12px;overflow-wrap:anywhere}
149
186
  @media (max-width:860px){header,.layout{grid-template-columns:1fr}.metrics{grid-template-columns:repeat(2,1fr)}.grid{grid-template-columns:1fr}.agents{grid-template-columns:1fr}}
187
+ @media (max-width:860px){.audit{grid-template-columns:1fr 1fr}}
150
188
  @media (max-width:520px){.shell{padding:14px}.metrics{grid-template-columns:1fr}.event{grid-template-columns:1fr}h1{font-size:32px}}
189
+ @media (max-width:520px){.audit{grid-template-columns:1fr}}
151
190
  </style>
152
191
  </head>
153
192
  <body>
@@ -167,6 +206,11 @@ const timelineHtml=timeline.length?'<div class="timeline">'+timeline.slice(-8).r
167
206
  const intentsHtml=intents.length?'<div class="timeline">'+intents.slice(-6).reverse().map(i=>\`<div class="event"><time>\${esc(i.at.replace('T',' ').slice(0,16))}</time><div><b>\${esc(i.actor)}</b> plans \${esc(i.action)}</div></div>\`).join('')+'</div>':'<div class="okline">No pending agent intents recorded.</div>';
168
207
  const policyHtml=entries(policy).length?\`<table>\${rows(policy)}</table>\`:'<div class="okline">No explicit version policy set.</div>';
169
208
  const card=(title,badge,body)=>\`<section class="card"><div class="card-head"><h2>\${title}</h2>\${badge||''}</div>\${body}</section>\`;
209
+ const reviewRequired=warnings.length>0||intents.length>0;
210
+ const recentChanges=timeline.slice(-8).length;
211
+ const nextAction=reviewRequired?'Review before environment changes':'Proceed with project-local work';
212
+ const auditItem=(key,value,hint,klass='')=>\`<div class="audit-item \${klass}"><div class="audit-k">\${key}</div><div class="audit-v">\${value}</div><div class="audit-hint">\${hint}</div></div>\`;
213
+ const handoffHtml=\`<table><tr><th>Status</th><td>\${reviewRequired?'review-required':'clear'}</td></tr><tr><th>Node</th><td><code>\${esc(manifest.runtimes.node||'not detected')}</code></td></tr><tr><th>Python</th><td><code>\${esc(manifest.runtimes.python||manifest.runtimes.python3||'not detected')}</code></td></tr><tr><th>Docker</th><td>\${manifest.containers?.docker?'available':'not detected'}</td></tr><tr><th>Next</th><td>\${reviewRequired?'Review warnings and open intents':'Continue project-local work'}</td></tr></table>\`;
170
214
  document.getElementById('app').innerHTML=\`
171
215
  <header>
172
216
  <div>
@@ -176,6 +220,12 @@ document.getElementById('app').innerHTML=\`
176
220
  </div>
177
221
  <div class="stamp"><b>\${warnings.length?'review':'clear'}</b><span>\${esc(manifest.workspace.name)}</span><span>\${esc(manifest.generatedAt)}</span></div>
178
222
  </header>
223
+ <section class="audit" aria-label="Audit summary">
224
+ \${auditItem('AI decision',reviewRequired?'review required':'can proceed',nextAction,reviewRequired?'review':'primary')}
225
+ \${auditItem('Open intents',String(intents.length),intents.length?'Resolve or coordinate before changes':'No pending env changes')}
226
+ \${auditItem('Warnings',String(warnings.length),warnings.length?'Policy or drift needs attention':'No warnings detected')}
227
+ \${auditItem('Recent changes',String(recentChanges),recentChanges?'Check ledger before continuing':'No recent env ledger entries')}
228
+ </section>
179
229
  <section class="metrics">
180
230
  <div class="metric"><div class="num">\${entries(manifest.runtimes).length}</div><div class="label">runtimes</div></div>
181
231
  <div class="metric"><div class="num">\${entries(manifest.packageManagers).length}</div><div class="label">package managers</div></div>
@@ -196,6 +246,8 @@ document.getElementById('app').innerHTML=\`
196
246
  <div style="height:14px"></div>
197
247
  \${card('Agent Intents','<span class="pill">'+intents.length+' open</span>',intentsHtml)}
198
248
  <div style="height:14px"></div>
249
+ \${card('AI Handoff',reviewRequired?'<span class="pill warn">review</span>':'<span class="pill">ready</span>',handoffHtml)}
250
+ <div style="height:14px"></div>
199
251
  \${card('Agent Pointers','<span class="pill">'+entries(manifest.agentFiles).filter(([,v])=>v).length+' detected</span>','<div class="agents">'+agentCards+'</div>')}
200
252
  <div style="height:14px"></div>
201
253
  \${card('Snapshot','',\`<table><tr><th>OS</th><td>\${esc(manifest.os.platform)} \${esc(manifest.os.release)} \${esc(manifest.os.arch)}</td></tr><tr><th>Shell</th><td>\${esc(manifest.os.shell||'unknown')}</td></tr><tr><th>Workspace</th><td><div class="path">\${esc(manifest.workspace.path)}</div></td></tr></table>\`)}