aienvmp 0.1.29 → 0.1.30
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 +6 -0
- package/README.md +1 -0
- package/package.json +1 -1
- package/src/commands/context.js +2 -0
- package/src/commands/dash.js +1 -1
- package/src/commands/doctor.js +4 -31
- package/src/commands/plan.js +2 -0
- package/src/enforcement.js +57 -0
- package/src/render.js +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.30
|
|
4
|
+
|
|
5
|
+
- Added shared enforcement advice for AI and CI surfaces.
|
|
6
|
+
- Exposed advisory-by-default behavior, suggested strict scopes, and scoped CI commands in context and plan outputs.
|
|
7
|
+
- Moved strict scope logic into a reusable enforcement module while keeping existing `doctor --strict` behavior compatible.
|
|
8
|
+
|
|
3
9
|
## 0.1.29
|
|
4
10
|
|
|
5
11
|
- Added lightweight remediation priority scoring for vulnerable packages.
|
package/README.md
CHANGED
|
@@ -97,6 +97,7 @@ aienvmp doctor --strict security # fail only scoped warnings
|
|
|
97
97
|
- read-only planning, no automatic fixes
|
|
98
98
|
- one advisory engine, optional enforcement with `doctor --ci`
|
|
99
99
|
- scoped enforcement with `doctor --strict security|policy|coordination|all`
|
|
100
|
+
- context and plan expose suggested strict scopes for CI
|
|
100
101
|
- non-blocking unless strict mode is explicitly requested
|
|
101
102
|
- security checks are opt-in and read-only
|
|
102
103
|
|
package/package.json
CHANGED
package/src/commands/context.js
CHANGED
|
@@ -7,6 +7,7 @@ import { loadPolicy, policyWarnings } from "../policy.js";
|
|
|
7
7
|
import { recommendedActions } from "../actions.js";
|
|
8
8
|
import { buildPlan, compactStepSummary } from "./plan.js";
|
|
9
9
|
import { aiDecision } from "../decision.js";
|
|
10
|
+
import { enforcementAdvice } from "../enforcement.js";
|
|
10
11
|
|
|
11
12
|
export async function contextWorkspace(args) {
|
|
12
13
|
const dir = workspaceDir(args);
|
|
@@ -23,6 +24,7 @@ export async function contextWorkspace(args) {
|
|
|
23
24
|
console.log(JSON.stringify({
|
|
24
25
|
status: warnings.length ? "review-required" : "clear",
|
|
25
26
|
decision,
|
|
27
|
+
enforcement: enforcementAdvice(warnings),
|
|
26
28
|
recommendedActions: actions,
|
|
27
29
|
stepSummary,
|
|
28
30
|
trust: manifest.trust || {},
|
package/src/commands/dash.js
CHANGED
|
@@ -8,7 +8,7 @@ import { dashboardPath, intentsPath, manifestPath, planJsonPath, planMdPath, tim
|
|
|
8
8
|
import { renderDashboard } from "../render.js";
|
|
9
9
|
import { loadPolicy, policyWarnings } from "../policy.js";
|
|
10
10
|
import { recommendedActions } from "../actions.js";
|
|
11
|
-
import { strictResult } from "
|
|
11
|
+
import { strictResult } from "../enforcement.js";
|
|
12
12
|
|
|
13
13
|
export async function dashWorkspace(args) {
|
|
14
14
|
const dir = workspaceDir(args);
|
package/src/commands/doctor.js
CHANGED
|
@@ -4,6 +4,9 @@ import { openIntents, readJsonl, readTimeline } from "../timeline.js";
|
|
|
4
4
|
import { intentsPath, manifestPath, timelinePath, workspaceDir } from "../paths.js";
|
|
5
5
|
import { loadPolicy, policyWarnings } from "../policy.js";
|
|
6
6
|
import { recommendedActions } from "../actions.js";
|
|
7
|
+
import { enforcementAdvice, strictResult } from "../enforcement.js";
|
|
8
|
+
|
|
9
|
+
export { strictResult } from "../enforcement.js";
|
|
7
10
|
|
|
8
11
|
export async function doctorWorkspace(args) {
|
|
9
12
|
const dir = workspaceDir(args);
|
|
@@ -23,6 +26,7 @@ export async function doctorWorkspace(args) {
|
|
|
23
26
|
openIntentCount: intents.length,
|
|
24
27
|
warnings,
|
|
25
28
|
recommendedActions: actions,
|
|
29
|
+
enforcement: enforcementAdvice(warnings),
|
|
26
30
|
strict
|
|
27
31
|
}, null, 2));
|
|
28
32
|
if (strict.fail) {
|
|
@@ -46,34 +50,3 @@ export async function doctorWorkspace(args) {
|
|
|
46
50
|
process.exitCode = 1;
|
|
47
51
|
}
|
|
48
52
|
}
|
|
49
|
-
|
|
50
|
-
export function strictResult(warnings = [], args = {}) {
|
|
51
|
-
const scope = normalizeStrictScope(args.strict || (args.ci ? "all" : ""));
|
|
52
|
-
const matchedWarnings = scope ? warnings.filter((warning) => warningMatchesScope(warning, scope)) : [];
|
|
53
|
-
return {
|
|
54
|
-
enabled: Boolean(scope),
|
|
55
|
-
scope: scope || "off",
|
|
56
|
-
fail: matchedWarnings.length > 0,
|
|
57
|
-
matchedWarningCodes: matchedWarnings.map((warning) => warning.code),
|
|
58
|
-
availableScopes: ["security", "policy", "coordination", "all"]
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function normalizeStrictScope(value) {
|
|
63
|
-
if (value === true) return "all";
|
|
64
|
-
const scope = String(value || "").trim().toLowerCase();
|
|
65
|
-
if (!scope || scope === "false" || scope === "off") return "";
|
|
66
|
-
if (["security", "policy", "coordination", "all"].includes(scope)) return scope;
|
|
67
|
-
return "all";
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function warningMatchesScope(warning, scope) {
|
|
71
|
-
if (scope === "all") return true;
|
|
72
|
-
return warningScope(warning.code) === scope;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function warningScope(code = "") {
|
|
76
|
-
if (code === "security-vulnerabilities") return "security";
|
|
77
|
-
if (["conflicting-open-intents", "stale-open-intent", "handoff-stale"].includes(code)) return "coordination";
|
|
78
|
-
return "policy";
|
|
79
|
-
}
|
package/src/commands/plan.js
CHANGED
|
@@ -7,6 +7,7 @@ import { renderPlan } from "../render.js";
|
|
|
7
7
|
import { recommendedActions } from "../actions.js";
|
|
8
8
|
import { openIntents, readJsonl, readTimeline } from "../timeline.js";
|
|
9
9
|
import { aiDecision } from "../decision.js";
|
|
10
|
+
import { enforcementAdvice } from "../enforcement.js";
|
|
10
11
|
|
|
11
12
|
export async function planWorkspace(args) {
|
|
12
13
|
const dir = workspaceDir(args);
|
|
@@ -41,6 +42,7 @@ export function buildPlan(manifest, warnings = [], intents = [], policy = {}) {
|
|
|
41
42
|
workspace: manifest.workspace || {},
|
|
42
43
|
trust: manifest.trust || {},
|
|
43
44
|
decision: aiDecision(warnings, intents),
|
|
45
|
+
enforcement: enforcementAdvice(warnings),
|
|
44
46
|
policy: {
|
|
45
47
|
node: policy.node || "not set",
|
|
46
48
|
python: policy.python || "not set",
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const STRICT_SCOPES = ["security", "policy", "coordination", "all"];
|
|
2
|
+
|
|
3
|
+
export function strictResult(warnings = [], args = {}) {
|
|
4
|
+
const scope = normalizeStrictScope(args.strict || (args.ci ? "all" : ""));
|
|
5
|
+
const matchedWarnings = scope ? warnings.filter((warning) => warningMatchesScope(warning, scope)) : [];
|
|
6
|
+
return {
|
|
7
|
+
enabled: Boolean(scope),
|
|
8
|
+
scope: scope || "off",
|
|
9
|
+
fail: matchedWarnings.length > 0,
|
|
10
|
+
matchedWarningCodes: matchedWarnings.map((warning) => warning.code),
|
|
11
|
+
availableScopes: STRICT_SCOPES
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function enforcementAdvice(warnings = []) {
|
|
16
|
+
const scopeResults = STRICT_SCOPES.map((scope) => {
|
|
17
|
+
const result = strictResult(warnings, { strict: scope });
|
|
18
|
+
return {
|
|
19
|
+
scope,
|
|
20
|
+
status: result.fail ? "fail" : "pass",
|
|
21
|
+
matchedWarningCodes: result.matchedWarningCodes
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
const suggestedStrictScopes = scopeResults
|
|
25
|
+
.filter((item) => item.scope !== "all" && item.status === "fail")
|
|
26
|
+
.map((item) => item.scope);
|
|
27
|
+
return {
|
|
28
|
+
mode: "advisory-by-default",
|
|
29
|
+
localBehavior: "non-blocking",
|
|
30
|
+
ciBehavior: "strict-only-when-requested",
|
|
31
|
+
suggestedStrictScopes,
|
|
32
|
+
scopes: scopeResults,
|
|
33
|
+
recommendedCommand: suggestedStrictScopes.length
|
|
34
|
+
? `aienvmp doctor --strict ${suggestedStrictScopes[0]}`
|
|
35
|
+
: "aienvmp doctor --strict all",
|
|
36
|
+
note: "Use strict mode in CI or explicit checks; do not block local operation unless the user requests it."
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function normalizeStrictScope(value) {
|
|
41
|
+
if (value === true) return "all";
|
|
42
|
+
const scope = String(value || "").trim().toLowerCase();
|
|
43
|
+
if (!scope || scope === "false" || scope === "off") return "";
|
|
44
|
+
if (STRICT_SCOPES.includes(scope)) return scope;
|
|
45
|
+
return "all";
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function warningMatchesScope(warning, scope) {
|
|
49
|
+
if (scope === "all") return true;
|
|
50
|
+
return warningScope(warning.code) === scope;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function warningScope(code = "") {
|
|
54
|
+
if (code === "security-vulnerabilities") return "security";
|
|
55
|
+
if (["conflicting-open-intents", "stale-open-intent", "handoff-stale"].includes(code)) return "coordination";
|
|
56
|
+
return "policy";
|
|
57
|
+
}
|
package/src/render.js
CHANGED
|
@@ -95,6 +95,7 @@ export function renderContext(manifest, timeline = [], warnings = [], intents =
|
|
|
95
95
|
`Status: ${status}`,
|
|
96
96
|
`Next: ${next}`,
|
|
97
97
|
"Project-local work: allowed; environment changes require intent and review when warnings or open intents exist.",
|
|
98
|
+
"Enforcement: advisory by default; use `aienvmp doctor --strict <scope>` only when explicit CI failure is wanted.",
|
|
98
99
|
`Trust: ${manifest.trust?.state || "observed"} (verified requires human or CI)`,
|
|
99
100
|
`Workspace: ${manifest.workspace.path}`,
|
|
100
101
|
`Node: ${manifest.runtimes.node || "not detected"}`,
|
|
@@ -175,6 +176,7 @@ export function renderPlan(plan) {
|
|
|
175
176
|
"",
|
|
176
177
|
`Status: ${plan.status}`,
|
|
177
178
|
`Decision: ${plan.decision?.mode || plan.status}`,
|
|
179
|
+
`Enforcement: ${plan.enforcement?.mode || "advisory-by-default"} (${plan.enforcement?.localBehavior || "non-blocking"})`,
|
|
178
180
|
`Generated: ${plan.generatedAt}`,
|
|
179
181
|
`Workspace: ${plan.workspace?.path || "unknown"}`,
|
|
180
182
|
"",
|