aienvmp 0.1.61 → 0.1.62
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 +10 -0
- package/README.md +1 -0
- package/package.json +1 -1
- package/src/commands/context.js +1 -0
- package/src/commands/status.js +1 -0
- package/src/commands/summary.js +3 -0
- package/src/contract.js +3 -2
- package/src/preflight.js +53 -0
- package/src/render.js +4 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.62
|
|
4
|
+
|
|
5
|
+
- Added a compact `collaboration` block to the shared preflight/status contract for multi-agent environment coordination.
|
|
6
|
+
- Exposed `collaboration` at the root of `context --json` so AI agents can read status, active targets, and the next command without digging through multiple sections.
|
|
7
|
+
- Added the collaboration status and rule to `.aienvmp/summary.md`.
|
|
8
|
+
- Added a short collaboration line to plain `aienvmp status` output.
|
|
9
|
+
- Added an `AI Collaboration` dashboard card with status, active targets, env-change rule, and next command.
|
|
10
|
+
- Documented the collaboration block in the stable schema contract and README.
|
|
11
|
+
- Added regression tests for status, context, summary, dashboard, and schema surfaces.
|
|
12
|
+
|
|
3
13
|
## 0.1.61
|
|
4
14
|
|
|
5
15
|
- Added an `aienvmp strict plan` block to the GitHub Action Step Summary.
|
package/README.md
CHANGED
|
@@ -51,6 +51,7 @@ AIENV.md # Markdown env map for AI agents
|
|
|
51
51
|
- `summary.md` is the short CI/AI handoff view, with `AI readiness`, signals, and next action first.
|
|
52
52
|
- `status.json.nextAgent` tells the next AI what to read and whether to review first.
|
|
53
53
|
- `aiReadiness` gives a one-field ready/review signal for AI continuation.
|
|
54
|
+
- `collaboration` gives the shortest multi-agent env-change status, targets, and next command.
|
|
54
55
|
- `dependencyReadSet` lists manifests and lockfiles before package or security changes.
|
|
55
56
|
- `sbomRisk` gives AI a compact light-SBOM risk level, signals, and next command.
|
|
56
57
|
- `sbom.json.aiDependencyReview` connects SBOM risk, scanner confidence, and safe dependency-change steps.
|
package/package.json
CHANGED
package/src/commands/context.js
CHANGED
|
@@ -27,6 +27,7 @@ export async function contextWorkspace(args) {
|
|
|
27
27
|
status: warnings.length ? "review-required" : "clear",
|
|
28
28
|
preflight,
|
|
29
29
|
aiReadiness: preflight.aiReadiness,
|
|
30
|
+
collaboration: preflight.collaboration,
|
|
30
31
|
coordination: preflight.coordination,
|
|
31
32
|
agentPointers: preflight.agentPointers,
|
|
32
33
|
sbomRisk: preflight.sbomRisk,
|
package/src/commands/status.js
CHANGED
|
@@ -23,6 +23,7 @@ export async function statusWorkspace(args) {
|
|
|
23
23
|
} else if (!args.quiet) {
|
|
24
24
|
console.log(`${output.state}: ${output.summary}`);
|
|
25
25
|
console.log(`ai-readiness: ${output.aiReadiness?.level || "unknown"} - ${output.aiReadiness?.next || "Run aienvmp context --json for details."}`);
|
|
26
|
+
console.log(`collaboration: ${output.collaboration?.status || "unknown"} - ${output.collaboration?.nextCommand || "aienvmp status --json"}`);
|
|
26
27
|
console.log(`next: ${output.nextCommand}`);
|
|
27
28
|
console.log(`ai: ${output.quickstart.readFirst} -> ${output.quickstart.detailCommand}`);
|
|
28
29
|
console.log(`intent: ${output.intentTargets[0]?.command || output.commands.recordIntent}`);
|
package/src/commands/summary.js
CHANGED
|
@@ -37,6 +37,7 @@ export function renderSummary(status = {}, manifest = {}) {
|
|
|
37
37
|
const sbomRisk = status.sbomRisk || manifest.lightSbom?.riskSummary || {};
|
|
38
38
|
const coordination = status.coordination || {};
|
|
39
39
|
const activity = status.agentActivity || {};
|
|
40
|
+
const collaboration = status.collaboration || {};
|
|
40
41
|
const workspace = manifest.workspace?.root || manifest.workspace?.name || ".";
|
|
41
42
|
const next = status.nextCommand || status.decision?.nextCommand || "aienvmp status";
|
|
42
43
|
const readFirst = status.nextAgent?.readFirst || ".aienvmp/status.json";
|
|
@@ -64,6 +65,7 @@ export function renderSummary(status = {}, manifest = {}) {
|
|
|
64
65
|
`- AI readiness: ${aiReadiness.level || "unknown"}`,
|
|
65
66
|
`- AI signals: ${aiSignals.length ? aiSignals.join("; ") : "none"}`,
|
|
66
67
|
`- AI next: ${aiNext}`,
|
|
68
|
+
`- AI collaboration: ${collaboration.status || "unknown"} / ${toList(collaboration.activeTargets).join(", ") || "none"} / ${collaboration.nextCommand || "aienvmp status --json"}`,
|
|
67
69
|
`- AI safe local work: ${toList(aiReadiness.safeProjectLocalActions)[0] || "read artifacts and avoid environment changes until reviewed"}`,
|
|
68
70
|
`- AI read first: ${readFirst}, then ${detail}`,
|
|
69
71
|
`- mode: advisory by default; strict is opt-in with ${strict}`,
|
|
@@ -79,6 +81,7 @@ export function renderSummary(status = {}, manifest = {}) {
|
|
|
79
81
|
"## AI handoff",
|
|
80
82
|
"",
|
|
81
83
|
`- environment changes: ${status.agentUse?.environmentChanges || "intent-and-review-first"}`,
|
|
84
|
+
`- collaboration rule: ${collaboration.rule || "Record intent before shared environment changes."}`,
|
|
82
85
|
`- coordination: ${coordination.next || "No open environment intents."}`,
|
|
83
86
|
`- recent agent activity: ${activity.next || "No environment records need coordination."}`,
|
|
84
87
|
`- conflict targets: ${conflictTargets.length ? conflictTargets.join(", ") : "none"}`,
|
package/src/contract.js
CHANGED
|
@@ -4,7 +4,7 @@ export function preflightContract() {
|
|
|
4
4
|
version: 1,
|
|
5
5
|
stability: "additive",
|
|
6
6
|
requiredFields: ["schemaVersion", "state", "decision", "quickstart", "commands", "artifacts"],
|
|
7
|
-
aiEntryFields: ["state", "summary", "aiReadiness", "nextAgent", "coordination", "agentActivity", "agentPointers", "sbomRisk", "followUps", "dependencyReadSet", "dependencyChangeProtocol"],
|
|
7
|
+
aiEntryFields: ["state", "summary", "aiReadiness", "collaboration", "nextAgent", "coordination", "agentActivity", "agentPointers", "sbomRisk", "followUps", "dependencyReadSet", "dependencyChangeProtocol"],
|
|
8
8
|
rule: "Consumers should ignore unknown fields and treat missing optional fields as unavailable."
|
|
9
9
|
};
|
|
10
10
|
}
|
|
@@ -29,7 +29,7 @@ export function schemaContract() {
|
|
|
29
29
|
},
|
|
30
30
|
context: {
|
|
31
31
|
command: "aienvmp context --json",
|
|
32
|
-
rootFields: ["status", "preflight", "aiReadiness", "coordination", "agentPointers", "decision", "enforcement", "recommendedActions", "workspace", "dependencySnapshot", "lightSbom", "warnings"]
|
|
32
|
+
rootFields: ["status", "preflight", "aiReadiness", "collaboration", "coordination", "agentPointers", "decision", "enforcement", "recommendedActions", "workspace", "dependencySnapshot", "lightSbom", "warnings"]
|
|
33
33
|
},
|
|
34
34
|
handoff: {
|
|
35
35
|
command: "aienvmp handoff --json",
|
|
@@ -56,6 +56,7 @@ export function schemaContract() {
|
|
|
56
56
|
consumerRule: "Ignore unknown fields. Do not require optional fields unless listed in requiredFields.",
|
|
57
57
|
localBehavior: "read-only; this command does not scan, install, update, or lock anything.",
|
|
58
58
|
aiReadinessRule: "When aiReadiness.level is review, project-local code work may still continue if aiReadiness.projectLocalWork is allowed; environment changes should follow intent/review guidance.",
|
|
59
|
+
collaborationRule: "Use collaboration.status, activeTargets, and nextCommand as the shortest multi-agent environment coordination hint.",
|
|
59
60
|
strictPlanRule: "Use enforcement.strictPlan or preflight.enforcementProfile.strictPlan to choose the narrowest explicit strict scope for CI."
|
|
60
61
|
}
|
|
61
62
|
};
|
package/src/preflight.js
CHANGED
|
@@ -19,6 +19,7 @@ export function buildPreflight(manifest = {}, warnings = [], intents = [], timel
|
|
|
19
19
|
const sbomRisk = manifest.lightSbom?.riskSummary || {};
|
|
20
20
|
const agentPointers = agentPointerSummary(manifest.agentFiles);
|
|
21
21
|
const aiReadiness = aiReadinessSummary({ state, decision, coordination, agentActivity, agentPointers, sbomRisk, followUps });
|
|
22
|
+
const collaboration = collaborationSummary({ state, decision, coordination, agentActivity, followUps, aiReadiness });
|
|
22
23
|
return {
|
|
23
24
|
schemaVersion: 1,
|
|
24
25
|
contract: preflightContract(),
|
|
@@ -61,6 +62,7 @@ export function buildPreflight(manifest = {}, warnings = [], intents = [], timel
|
|
|
61
62
|
nextAgent: nextAgentHint(state, dependencyReadSet, dependencyChangeProtocol),
|
|
62
63
|
coordination,
|
|
63
64
|
agentActivity,
|
|
65
|
+
collaboration,
|
|
64
66
|
agentPointers,
|
|
65
67
|
aiReadiness,
|
|
66
68
|
sbomRisk,
|
|
@@ -92,6 +94,45 @@ export function buildPreflight(manifest = {}, warnings = [], intents = [], timel
|
|
|
92
94
|
};
|
|
93
95
|
}
|
|
94
96
|
|
|
97
|
+
function collaborationSummary({ state, decision, coordination, agentActivity, followUps, aiReadiness }) {
|
|
98
|
+
const conflictTargets = coordination?.conflictTargets || [];
|
|
99
|
+
const multiActorTargets = agentActivity?.multiActorTargets || [];
|
|
100
|
+
const followUpTargets = (followUps || []).map((item) => item.target || "environment");
|
|
101
|
+
const activeTargets = unique([...conflictTargets, ...multiActorTargets, ...followUpTargets]);
|
|
102
|
+
const reviewSignals = [];
|
|
103
|
+
if (conflictTargets.length) reviewSignals.push("open intent conflict");
|
|
104
|
+
if (multiActorTargets.length) reviewSignals.push("multi-agent environment record");
|
|
105
|
+
if ((followUps || []).length) reviewSignals.push("pending post-change follow-up");
|
|
106
|
+
if (state !== "clear") reviewSignals.push("preflight review required");
|
|
107
|
+
|
|
108
|
+
const nextCommand = firstFollowUpCommand(followUps)
|
|
109
|
+
|| (multiActorTargets.length ? "aienvmp handoff --record --actor agent:id" : "")
|
|
110
|
+
|| (conflictTargets.length ? "aienvmp plan --write" : "")
|
|
111
|
+
|| (decision?.canChangeEnvironmentWithoutReview
|
|
112
|
+
? "aienvmp intent --actor agent:id --action planned-change --target environment"
|
|
113
|
+
: "aienvmp context --json");
|
|
114
|
+
|
|
115
|
+
const status = reviewSignals.length ? "review-before-env-change" : "clear";
|
|
116
|
+
return {
|
|
117
|
+
status,
|
|
118
|
+
mode: "advisory",
|
|
119
|
+
activeTargets,
|
|
120
|
+
reviewSignals,
|
|
121
|
+
projectLocalWork: aiReadiness?.projectLocalWork || (decision?.canContinueProjectLocalWork ? "allowed" : "review-first"),
|
|
122
|
+
environmentChanges: reviewSignals.length ? "intent-review-handoff-first" : "intent-first",
|
|
123
|
+
nextCommand,
|
|
124
|
+
rule: reviewSignals.length
|
|
125
|
+
? "Do not install, remove, upgrade, downgrade, or switch shared environment tools until the listed collaboration signals are reviewed."
|
|
126
|
+
: "Multiple AI agents may continue project-local work; record intent before shared environment changes.",
|
|
127
|
+
commands: {
|
|
128
|
+
read: "aienvmp status --json",
|
|
129
|
+
plan: "aienvmp plan --write",
|
|
130
|
+
handoff: "aienvmp handoff --record --actor agent:id",
|
|
131
|
+
checkpoint: "aienvmp checkpoint --actor agent:id --summary what-changed --target environment"
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
95
136
|
function aiReadinessSummary({ state, decision, coordination, agentActivity, agentPointers, sbomRisk, followUps }) {
|
|
96
137
|
const blockers = [];
|
|
97
138
|
const review = [];
|
|
@@ -429,6 +470,18 @@ function normalizeTarget(target = "") {
|
|
|
429
470
|
return normalized;
|
|
430
471
|
}
|
|
431
472
|
|
|
473
|
+
function unique(items = []) {
|
|
474
|
+
return [...new Set(items.map((item) => normalizeTarget(item)).filter(Boolean))];
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
function firstFollowUpCommand(followUps = []) {
|
|
478
|
+
for (const item of followUps || []) {
|
|
479
|
+
const command = item.commands?.find(Boolean);
|
|
480
|
+
if (command) return command;
|
|
481
|
+
}
|
|
482
|
+
return "";
|
|
483
|
+
}
|
|
484
|
+
|
|
432
485
|
function agentQuickstart(reviewRequired) {
|
|
433
486
|
return {
|
|
434
487
|
label: "10-second AI flow",
|
package/src/render.js
CHANGED
|
@@ -484,6 +484,8 @@ const followUpsHtml=followUps.length?'<div class="timeline">'+followUps.slice(0,
|
|
|
484
484
|
const agentActivity=manifest.preflight?.agentActivity||{};
|
|
485
485
|
const activityTargets=agentActivity.targets||[];
|
|
486
486
|
const activityHtml=activityTargets.length?'<div class="timeline">'+activityTargets.slice(0,5).map(a=>\`<div class="event"><time>\${esc(a.target||'env')}</time><div><b>\${esc((a.actors||[]).join(', ')||'unknown')}</b> \${esc(a.count||0)} record(s) \${a.multiActor?'<code>multi-agent</code>':'<code>single-agent</code>'}\${a.latestSummary?\`<div class="path">\${esc(a.latestSummary)}</div>\`:''}</div></div>\`).join('')+'</div><div class="path">'+esc(agentActivity.next||'Review activity before environment changes.')+'</div>':'<div class="okline">No recorded environment activity needs coordination.</div>';
|
|
487
|
+
const collaboration=manifest.preflight?.collaboration||{};
|
|
488
|
+
const collaborationHtml=\`<table><tr><th>Status</th><td><code>\${esc(collaboration.status||'unknown')}</code> \${esc(collaboration.mode||'advisory')}</td></tr><tr><th>Targets</th><td>\${esc((collaboration.activeTargets||[]).join(', ')||'none')}</td></tr><tr><th>Project work</th><td><code>\${esc(collaboration.projectLocalWork||'allowed')}</code></td></tr><tr><th>Env changes</th><td><code>\${esc(collaboration.environmentChanges||'intent-first')}</code></td></tr><tr><th>Next</th><td><code>\${esc(collaboration.nextCommand||'aienvmp status --json')}</code></td></tr></table><div class="timeline">\${(collaboration.reviewSignals||[]).slice(0,4).map(signal=>\`<div class="event"><time>review</time><div>\${esc(signal)}</div></div>\`).join('')}</div><div class="path">\${esc(collaboration.rule||'Record intent before shared environment changes.')}</div>\`;
|
|
487
489
|
const dependencyReadSet=manifest.preflight?.dependencyReadSet||[];
|
|
488
490
|
const dependencyReadSetHtml=dependencyReadSet.length?'<div class="timeline">'+dependencyReadSet.slice(0,5).map(d=>\`<div class="event"><time>\${esc(d.ecosystem||'deps')}</time><div><b>\${esc(d.manifest||'dependency files')}</b> <code>\${esc(d.manager||'unknown')}</code><div class="path">\${esc([d.manifest,...(d.lockfiles||[])].filter(Boolean).join(', '))}</div>\${d.riskPackages?.length?\`<div class="path">risk: \${esc(d.riskPackages.join(', '))}</div>\`:''}</div></div>\`).join('')+'</div>':'<div class="okline">No dependency files detected.</div>';
|
|
489
491
|
const dependencyProtocol=manifest.preflight?.dependencyChangeProtocol||{};
|
|
@@ -546,6 +548,8 @@ document.getElementById('app').innerHTML=\`
|
|
|
546
548
|
<div style="height:14px"></div>
|
|
547
549
|
\${card('Agent Activity',agentActivity.multiActorTargets?.length?'<span class="pill warn">'+agentActivity.multiActorTargets.length+' shared</span>':'<span class="pill">clear</span>',activityHtml)}
|
|
548
550
|
<div style="height:14px"></div>
|
|
551
|
+
\${card('AI Collaboration',collaboration.status==='clear'?'<span class="pill">clear</span>':'<span class="pill warn">review</span>',collaborationHtml)}
|
|
552
|
+
<div style="height:14px"></div>
|
|
549
553
|
\${card('AI Contract','<span class="pill">'+(contract.stability||'additive')+'</span>',contractHtml)}
|
|
550
554
|
<div style="height:14px"></div>
|
|
551
555
|
\${card('Dependency Read Set','<span class="pill">'+dependencyReadSet.length+' files</span>',dependencyReadSetHtml)}
|