aienvmp 0.1.25 → 0.1.26

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.26
4
+
5
+ - Shared one AI decision contract across `context --json`, `plan`, and `handoff`.
6
+ - Added decision mode and required command guidance to plan and handoff outputs.
7
+ - Reduced duplicated guidance so multiple AI agents receive the same environment-change rules.
8
+
3
9
  ## 0.1.25
4
10
 
5
11
  - Added a more explicit AI decision contract to `context --json`.
package/README.md CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
  It helps Codex, Claude, Gemini, and humans avoid silent Node, Python, package manager, Docker, and security drift.
12
12
 
13
- Core loop: scan once, give AI a preflight context, write a read-only action plan, and hand off safe next steps.
13
+ Core loop: scan once, give AI a shared decision contract, write a read-only action plan, and hand off safe next steps.
14
14
 
15
15
  ## Quick Start
16
16
 
@@ -81,8 +81,8 @@ The dashboard shows which strict scopes are CI-ready before you enforce them.
81
81
  aienvmp sync # update env map, light SBOM, ledger, dashboard
82
82
  aienvmp context # AI preflight brief
83
83
  aienvmp context --json # AI decision contract + actions + compact step summary
84
- aienvmp plan # read-only AI action plan for drift and remediation
85
- aienvmp handoff # next-agent handoff summary + recommended actions
84
+ aienvmp plan # read-only AI action plan using the same decision contract
85
+ aienvmp handoff # next-agent handoff summary using the same decision contract
86
86
  aienvmp intent # record a planned env change
87
87
  aienvmp record # record what changed
88
88
  aienvmp doctor --ci # strict CI check for all warnings
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aienvmp",
3
- "version": "0.1.25",
3
+ "version": "0.1.26",
4
4
  "description": "AI-first environment maps and lightweight runtime SBOMs for shared development machines.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -6,6 +6,7 @@ import { renderContext } from "../render.js";
6
6
  import { loadPolicy, policyWarnings } from "../policy.js";
7
7
  import { recommendedActions } from "../actions.js";
8
8
  import { buildPlan, compactStepSummary } from "./plan.js";
9
+ import { aiDecision } from "../decision.js";
9
10
 
10
11
  export async function contextWorkspace(args) {
11
12
  const dir = workspaceDir(args);
@@ -15,7 +16,7 @@ export async function contextWorkspace(args) {
15
16
  const intents = openIntents(await readJsonl(intentsPath(dir)));
16
17
  const policy = await loadPolicy(dir);
17
18
  const warnings = [...diagnose(manifest, { timeline, intents }), ...policyWarnings(manifest, policy)];
18
- const decision = contextDecision(warnings, intents);
19
+ const decision = aiDecision(warnings, intents);
19
20
  const actions = recommendedActions(manifest, { warnings, intents });
20
21
  const stepSummary = compactStepSummary(buildPlan(manifest, warnings, intents, policy));
21
22
  if (args.json) {
@@ -61,40 +62,3 @@ function inventorySummary(inventory = {}) {
61
62
  groups: Object.fromEntries(Object.entries(tools).map(([name, items]) => [name, items.length]))
62
63
  };
63
64
  }
64
-
65
- function contextDecision(warnings, intents) {
66
- const warningCodes = warnings.map((warning) => warning.code);
67
- const reviewRequired = warnings.length > 0 || intents.length > 0;
68
- const canChangeEnvironmentWithoutReview = !reviewRequired;
69
- const mode = reviewRequired ? "review-first" : "project-local-work";
70
- return {
71
- schemaVersion: 1,
72
- mode,
73
- canProceed: !reviewRequired,
74
- canContinueProjectLocalWork: true,
75
- canChangeEnvironmentWithoutReview,
76
- safeForProjectLocalWork: warnings.length === 0,
77
- reviewRequired,
78
- warningCodes,
79
- environmentChangeRequiresIntent: true,
80
- globalEnvironmentChangesRequireUserApproval: true,
81
- pendingIntentCount: intents.length,
82
- mustNotDo: [
83
- "do not change global runtimes without user approval",
84
- "do not install or remove global package managers without user approval",
85
- "do not change Docker daemon/context assumptions without user approval",
86
- "do not ignore open intents or review-required warnings"
87
- ],
88
- recommendedNextActions: warnings.length
89
- ? ["review warnings", "ask the user before environment changes", "record intent before changes"]
90
- : ["continue with project-local work", "run aienvmp intent before environment changes"],
91
- requiredCommands: {
92
- beforeEnvironmentChange: "aienvmp intent --actor agent:id --action planned-change --target <runtime|package-manager|docker>",
93
- refreshAfterChange: "aienvmp sync",
94
- recordAfterChange: "aienvmp record --actor agent:id --summary what-changed",
95
- handoff: "aienvmp handoff --record --actor agent:id",
96
- reviewPlan: "aienvmp plan"
97
- },
98
- nextCommand: reviewRequired ? "aienvmp plan" : "continue project-local work; use aienvmp intent before environment changes"
99
- };
100
- }
@@ -6,6 +6,7 @@ import { renderHandoff } from "../render.js";
6
6
  import { openIntents, readJsonl, readTimeline } from "../timeline.js";
7
7
  import { changedTrust } from "../trust.js";
8
8
  import { recommendedActions } from "../actions.js";
9
+ import { aiDecision } from "../decision.js";
9
10
 
10
11
  export async function handoffWorkspace(args) {
11
12
  const dir = workspaceDir(args);
@@ -48,6 +49,7 @@ export function buildHandoff(manifest, timeline = [], warnings = [], intents = [
48
49
  status: reviewRequired ? "review-required" : "clear",
49
50
  trust: manifest.trust || {},
50
51
  schemaVersion: manifest.schemaVersion || 1,
52
+ decision: aiDecision(warnings, intents),
51
53
  workspace: manifest.workspace,
52
54
  safeRuntime: {
53
55
  node: manifest.runtimes?.node || "not detected",
@@ -6,6 +6,7 @@ import { intentsPath, manifestPath, planJsonPath, planMdPath, timelinePath, work
6
6
  import { renderPlan } from "../render.js";
7
7
  import { recommendedActions } from "../actions.js";
8
8
  import { openIntents, readJsonl, readTimeline } from "../timeline.js";
9
+ import { aiDecision } from "../decision.js";
9
10
 
10
11
  export async function planWorkspace(args) {
11
12
  const dir = workspaceDir(args);
@@ -39,6 +40,7 @@ export function buildPlan(manifest, warnings = [], intents = [], policy = {}) {
39
40
  status,
40
41
  workspace: manifest.workspace || {},
41
42
  trust: manifest.trust || {},
43
+ decision: aiDecision(warnings, intents),
42
44
  policy: {
43
45
  node: policy.node || "not set",
44
46
  python: policy.python || "not set",
@@ -0,0 +1,35 @@
1
+ export function aiDecision(warnings = [], intents = []) {
2
+ const warningCodes = warnings.map((warning) => warning.code).filter(Boolean);
3
+ const reviewRequired = warnings.length > 0 || intents.length > 0;
4
+ const mode = reviewRequired ? "review-first" : "project-local-work";
5
+ return {
6
+ schemaVersion: 1,
7
+ mode,
8
+ canProceed: !reviewRequired,
9
+ canContinueProjectLocalWork: true,
10
+ canChangeEnvironmentWithoutReview: !reviewRequired,
11
+ safeForProjectLocalWork: warnings.length === 0,
12
+ reviewRequired,
13
+ warningCodes,
14
+ environmentChangeRequiresIntent: true,
15
+ globalEnvironmentChangesRequireUserApproval: true,
16
+ pendingIntentCount: intents.length,
17
+ mustNotDo: [
18
+ "do not change global runtimes without user approval",
19
+ "do not install or remove global package managers without user approval",
20
+ "do not change Docker daemon/context assumptions without user approval",
21
+ "do not ignore open intents or review-required warnings"
22
+ ],
23
+ recommendedNextActions: reviewRequired
24
+ ? ["review warnings and open intents", "ask the user before environment changes", "record intent before changes"]
25
+ : ["continue with project-local work", "run aienvmp intent before environment changes"],
26
+ requiredCommands: {
27
+ beforeEnvironmentChange: "aienvmp intent --actor agent:id --action planned-change --target <runtime|package-manager|docker>",
28
+ refreshAfterChange: "aienvmp sync",
29
+ recordAfterChange: "aienvmp record --actor agent:id --summary what-changed",
30
+ handoff: "aienvmp handoff --record --actor agent:id",
31
+ reviewPlan: "aienvmp plan"
32
+ },
33
+ nextCommand: reviewRequired ? "aienvmp plan" : "continue project-local work; use aienvmp intent before environment changes"
34
+ };
35
+ }
package/src/render.js CHANGED
@@ -133,6 +133,7 @@ export function renderHandoff(handoff) {
133
133
  "# AI Handoff",
134
134
  "",
135
135
  `Status: ${handoff.status}`,
136
+ `Decision: ${handoff.decision?.mode || handoff.status}`,
136
137
  `Trust: ${handoff.trust?.state || "observed"} (not AI-verified)`,
137
138
  `Schema: ${handoff.schemaVersion}`,
138
139
  `Workspace: ${handoff.workspace?.path || "unknown"}`,
@@ -170,6 +171,7 @@ export function renderPlan(plan) {
170
171
  "# AI Environment Plan",
171
172
  "",
172
173
  `Status: ${plan.status}`,
174
+ `Decision: ${plan.decision?.mode || plan.status}`,
173
175
  `Generated: ${plan.generatedAt}`,
174
176
  `Workspace: ${plan.workspace?.path || "unknown"}`,
175
177
  "",