aienvmp 0.1.15 → 0.1.16

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.16
4
+
5
+ - Added scoped strict checks with `doctor --strict security|policy|coordination|all`.
6
+ - Kept `doctor --ci` compatible as strict `all`.
7
+ - Updated the GitHub Action `strict` input to support scoped enforcement while keeping advisory mode by default.
8
+
3
9
  ## 0.1.15
4
10
 
5
11
  - Added dashboard links for written AI plan artifacts.
package/README.md CHANGED
@@ -63,7 +63,8 @@ aienvmp plan # read-only AI action plan, no automatic fixes
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
66
- aienvmp doctor --ci # strict CI check
66
+ aienvmp doctor --ci # strict CI check for all warnings
67
+ aienvmp doctor --strict security # fail only scoped warnings
67
68
  ```
68
69
 
69
70
  ## Principles
@@ -72,6 +73,7 @@ aienvmp doctor --ci # strict CI check
72
73
  - AI-first
73
74
  - lightweight
74
75
  - one advisory engine, optional enforcement with `doctor --ci`
76
+ - scoped enforcement with `doctor --strict security|policy|coordination|all`
75
77
  - non-blocking unless strict mode is explicitly requested
76
78
  - security checks are opt-in and read-only
77
79
 
package/action.yml CHANGED
@@ -8,9 +8,9 @@ inputs:
8
8
  required: false
9
9
  default: "."
10
10
  strict:
11
- description: Fail when doctor reports warnings
11
+ description: Fail when doctor reports scoped warnings
12
12
  required: false
13
- default: "false"
13
+ default: "off"
14
14
  write-plan:
15
15
  description: Write read-only AI plan artifacts
16
16
  required: false
@@ -35,6 +35,8 @@ runs:
35
35
  run: |
36
36
  if [ "${{ inputs.strict }}" = "true" ]; then
37
37
  node "$GITHUB_ACTION_PATH/bin/aienvmp.js" doctor --dir "${{ inputs.directory }}" --ci
38
+ elif [ "${{ inputs.strict }}" != "false" ] && [ "${{ inputs.strict }}" != "off" ]; then
39
+ node "$GITHUB_ACTION_PATH/bin/aienvmp.js" doctor --dir "${{ inputs.directory }}" --strict "${{ inputs.strict }}"
38
40
  else
39
41
  node "$GITHUB_ACTION_PATH/bin/aienvmp.js" doctor --dir "${{ inputs.directory }}"
40
42
  fi
@@ -14,4 +14,4 @@ jobs:
14
14
  with:
15
15
  directory: "."
16
16
  write-plan: "true"
17
- strict: "false"
17
+ strict: "off" # security, policy, coordination, all, or off
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aienvmp",
3
- "version": "0.1.15",
3
+ "version": "0.1.16",
4
4
  "description": "AI-first environment maps and lightweight runtime SBOMs for shared development machines.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli.js CHANGED
@@ -98,7 +98,7 @@ Advanced:
98
98
  aienvmp snippet [agents|claude|gemini] [--write AGENTS.md]
99
99
  aienvmp compile [--dir .]
100
100
  aienvmp diff [--dir .]
101
- aienvmp doctor [--dir .] [--json] [--ci]
101
+ aienvmp doctor [--dir .] [--json] [--ci] [--strict security|policy|coordination|all]
102
102
  aienvmp dash [--dir .] [--open]
103
103
  `);
104
104
  }
@@ -14,16 +14,18 @@ export async function doctorWorkspace(args) {
14
14
  const intents = openIntents(await readJsonl(intentsPath(dir)));
15
15
  const warnings = [...diagnose(manifest, { timeline, intents }), ...policyWarnings(manifest, policy)];
16
16
  const actions = recommendedActions(manifest, { warnings, intents });
17
+ const strict = strictResult(warnings, args);
17
18
  if (args.json) {
18
19
  console.log(JSON.stringify({
19
- status: warnings.length ? "warning" : "ok",
20
+ status: strict.fail ? "fail" : warnings.length ? "warning" : "ok",
20
21
  trust: manifest.trust || {},
21
22
  policy,
22
23
  openIntentCount: intents.length,
23
24
  warnings,
24
- recommendedActions: actions
25
+ recommendedActions: actions,
26
+ strict
25
27
  }, null, 2));
26
- if (args.ci && warnings.length) {
28
+ if (strict.fail) {
27
29
  process.exitCode = 1;
28
30
  }
29
31
  return;
@@ -39,8 +41,39 @@ export async function doctorWorkspace(args) {
39
41
  for (const item of actions) {
40
42
  console.log(`- [${item.priority}] ${item.summary}${item.command ? ` (${item.command})` : ""}`);
41
43
  }
42
- console.log("doctor: warnings are non-blocking by default; pass --ci to fail automation.");
43
- if (args.ci) {
44
+ console.log(`doctor: warnings are non-blocking by default; pass --ci or --strict ${strict.availableScopes.join("|")} to fail automation.`);
45
+ if (strict.fail) {
44
46
  process.exitCode = 1;
45
47
  }
46
48
  }
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
+ }