@codyswann/lisa 2.316.2 → 2.317.1

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.
Files changed (212) hide show
  1. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  2. package/dist/core/upstream-evidence-manifest.js +139 -9
  3. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  4. package/package.json +1 -1
  5. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  6. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  7. package/plugins/lisa/.codex-plugin/skills/lisa-atlassian-access/SKILL.md +17 -0
  8. package/plugins/lisa/.codex-plugin/skills/lisa-automation-status/SKILL.md +23 -0
  9. package/plugins/lisa/.codex-plugin/skills/lisa-doctor/SKILL.md +33 -0
  10. package/plugins/lisa/.codex-plugin/skills/lisa-implement/SKILL.md +17 -0
  11. package/plugins/lisa/.codex-plugin/skills/lisa-notion-access/SKILL.md +17 -0
  12. package/plugins/lisa/.codex-plugin/skills/lisa-remote-dispatch/SKILL.md +106 -0
  13. package/plugins/lisa/.codex-plugin/skills/lisa-remote-dispatch/agents/openai.yaml +4 -0
  14. package/plugins/lisa/.codex-plugin/skills/lisa-remote-dispatch/scripts/dispatch.mjs +264 -0
  15. package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/SKILL.md +137 -51
  16. package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/doctor-secrets.mjs +217 -0
  17. package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/envfile.mjs +78 -0
  18. package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +105 -0
  19. package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/providers.mjs +240 -0
  20. package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/read-secret-note.mjs +82 -0
  21. package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/resolve-secret.mjs +151 -176
  22. package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/rotate-secret.mjs +266 -0
  23. package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/surfaces.mjs +147 -0
  24. package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/validate-config.mjs +224 -0
  25. package/plugins/lisa/.codex-plugin/skills/lisa-setup-automations/SKILL.md +69 -0
  26. package/plugins/lisa/.codex-plugin/skills/lisa-setup-automations/scripts/generate-workflow.mjs +185 -0
  27. package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/SKILL.md +150 -0
  28. package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/agents/openai.yaml +4 -0
  29. package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/assets/setup.sh +45 -0
  30. package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +227 -0
  31. package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/scripts/toolchain.mjs +169 -0
  32. package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/scripts/verify-remote-env.mjs +186 -0
  33. package/plugins/lisa/commands/implement.md +5 -3
  34. package/plugins/lisa/commands/setup/remote-env.md +7 -0
  35. package/plugins/lisa/skills/lisa-atlassian-access/SKILL.md +17 -0
  36. package/plugins/lisa/skills/lisa-automation-status/SKILL.md +23 -0
  37. package/plugins/lisa/skills/lisa-doctor/SKILL.md +33 -0
  38. package/plugins/lisa/skills/lisa-implement/SKILL.md +17 -0
  39. package/plugins/lisa/skills/lisa-notion-access/SKILL.md +17 -0
  40. package/plugins/lisa/skills/lisa-remote-dispatch/SKILL.md +106 -0
  41. package/plugins/lisa/skills/lisa-remote-dispatch/agents/openai.yaml +4 -0
  42. package/plugins/lisa/skills/lisa-remote-dispatch/scripts/dispatch.mjs +264 -0
  43. package/plugins/lisa/skills/lisa-secrets-access/SKILL.md +138 -52
  44. package/plugins/lisa/skills/lisa-secrets-access/scripts/doctor-secrets.mjs +217 -0
  45. package/plugins/lisa/skills/lisa-secrets-access/scripts/envfile.mjs +78 -0
  46. package/plugins/lisa/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +105 -0
  47. package/plugins/lisa/skills/lisa-secrets-access/scripts/providers.mjs +240 -0
  48. package/plugins/lisa/skills/lisa-secrets-access/scripts/read-secret-note.mjs +82 -0
  49. package/plugins/lisa/skills/lisa-secrets-access/scripts/resolve-secret.mjs +151 -176
  50. package/plugins/lisa/skills/lisa-secrets-access/scripts/rotate-secret.mjs +266 -0
  51. package/plugins/lisa/skills/lisa-secrets-access/scripts/surfaces.mjs +147 -0
  52. package/plugins/lisa/skills/lisa-secrets-access/scripts/validate-config.mjs +224 -0
  53. package/plugins/lisa/skills/lisa-setup-automations/SKILL.md +69 -0
  54. package/plugins/lisa/skills/lisa-setup-automations/scripts/generate-workflow.mjs +185 -0
  55. package/plugins/lisa/skills/lisa-setup-remote-env/SKILL.md +150 -0
  56. package/plugins/lisa/skills/lisa-setup-remote-env/agents/openai.yaml +4 -0
  57. package/plugins/lisa/skills/lisa-setup-remote-env/assets/setup.sh +45 -0
  58. package/plugins/lisa/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +227 -0
  59. package/plugins/lisa/skills/lisa-setup-remote-env/scripts/toolchain.mjs +169 -0
  60. package/plugins/lisa/skills/lisa-setup-remote-env/scripts/verify-remote-env.mjs +186 -0
  61. package/plugins/lisa-agy/commands/lisa/implement.md +5 -3
  62. package/plugins/lisa-agy/commands/lisa/setup/remote-env.md +7 -0
  63. package/plugins/lisa-agy/plugin.json +1 -1
  64. package/plugins/lisa-agy/skills/lisa-atlassian-access/SKILL.md +17 -0
  65. package/plugins/lisa-agy/skills/lisa-automation-status/SKILL.md +23 -0
  66. package/plugins/lisa-agy/skills/lisa-doctor/SKILL.md +33 -0
  67. package/plugins/lisa-agy/skills/lisa-implement/SKILL.md +17 -0
  68. package/plugins/lisa-agy/skills/lisa-notion-access/SKILL.md +17 -0
  69. package/plugins/lisa-agy/skills/lisa-remote-dispatch/SKILL.md +106 -0
  70. package/plugins/lisa-agy/skills/lisa-remote-dispatch/scripts/dispatch.mjs +264 -0
  71. package/plugins/lisa-agy/skills/lisa-secrets-access/SKILL.md +138 -52
  72. package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/doctor-secrets.mjs +217 -0
  73. package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/envfile.mjs +78 -0
  74. package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +105 -0
  75. package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/providers.mjs +240 -0
  76. package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/read-secret-note.mjs +82 -0
  77. package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/resolve-secret.mjs +151 -176
  78. package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/rotate-secret.mjs +266 -0
  79. package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/surfaces.mjs +147 -0
  80. package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/validate-config.mjs +224 -0
  81. package/plugins/lisa-agy/skills/lisa-setup-automations/SKILL.md +69 -0
  82. package/plugins/lisa-agy/skills/lisa-setup-automations/scripts/generate-workflow.mjs +185 -0
  83. package/plugins/lisa-agy/skills/lisa-setup-remote-env/SKILL.md +150 -0
  84. package/plugins/lisa-agy/skills/lisa-setup-remote-env/assets/setup.sh +45 -0
  85. package/plugins/lisa-agy/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +227 -0
  86. package/plugins/lisa-agy/skills/lisa-setup-remote-env/scripts/toolchain.mjs +169 -0
  87. package/plugins/lisa-agy/skills/lisa-setup-remote-env/scripts/verify-remote-env.mjs +186 -0
  88. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  89. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  90. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  91. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  92. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  93. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  94. package/plugins/lisa-copilot/commands/lisa/implement.md +5 -3
  95. package/plugins/lisa-copilot/commands/lisa/setup/remote-env.md +7 -0
  96. package/plugins/lisa-copilot/skills/lisa-atlassian-access/SKILL.md +17 -0
  97. package/plugins/lisa-copilot/skills/lisa-automation-status/SKILL.md +23 -0
  98. package/plugins/lisa-copilot/skills/lisa-doctor/SKILL.md +33 -0
  99. package/plugins/lisa-copilot/skills/lisa-implement/SKILL.md +17 -0
  100. package/plugins/lisa-copilot/skills/lisa-notion-access/SKILL.md +17 -0
  101. package/plugins/lisa-copilot/skills/lisa-remote-dispatch/SKILL.md +106 -0
  102. package/plugins/lisa-copilot/skills/lisa-remote-dispatch/scripts/dispatch.mjs +264 -0
  103. package/plugins/lisa-copilot/skills/lisa-secrets-access/SKILL.md +138 -52
  104. package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/doctor-secrets.mjs +217 -0
  105. package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/envfile.mjs +78 -0
  106. package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +105 -0
  107. package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/providers.mjs +240 -0
  108. package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/read-secret-note.mjs +82 -0
  109. package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/resolve-secret.mjs +151 -176
  110. package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/rotate-secret.mjs +266 -0
  111. package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/surfaces.mjs +147 -0
  112. package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/validate-config.mjs +224 -0
  113. package/plugins/lisa-copilot/skills/lisa-setup-automations/SKILL.md +69 -0
  114. package/plugins/lisa-copilot/skills/lisa-setup-automations/scripts/generate-workflow.mjs +185 -0
  115. package/plugins/lisa-copilot/skills/lisa-setup-remote-env/SKILL.md +150 -0
  116. package/plugins/lisa-copilot/skills/lisa-setup-remote-env/assets/setup.sh +45 -0
  117. package/plugins/lisa-copilot/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +227 -0
  118. package/plugins/lisa-copilot/skills/lisa-setup-remote-env/scripts/toolchain.mjs +169 -0
  119. package/plugins/lisa-copilot/skills/lisa-setup-remote-env/scripts/verify-remote-env.mjs +186 -0
  120. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  121. package/plugins/lisa-cursor/commands/lisa/implement.md +5 -3
  122. package/plugins/lisa-cursor/commands/lisa/setup/remote-env.md +7 -0
  123. package/plugins/lisa-cursor/skills/lisa-atlassian-access/SKILL.md +17 -0
  124. package/plugins/lisa-cursor/skills/lisa-automation-status/SKILL.md +23 -0
  125. package/plugins/lisa-cursor/skills/lisa-doctor/SKILL.md +33 -0
  126. package/plugins/lisa-cursor/skills/lisa-implement/SKILL.md +17 -0
  127. package/plugins/lisa-cursor/skills/lisa-notion-access/SKILL.md +17 -0
  128. package/plugins/lisa-cursor/skills/lisa-remote-dispatch/SKILL.md +106 -0
  129. package/plugins/lisa-cursor/skills/lisa-remote-dispatch/scripts/dispatch.mjs +264 -0
  130. package/plugins/lisa-cursor/skills/lisa-secrets-access/SKILL.md +138 -52
  131. package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/doctor-secrets.mjs +217 -0
  132. package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/envfile.mjs +78 -0
  133. package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +105 -0
  134. package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/providers.mjs +240 -0
  135. package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/read-secret-note.mjs +82 -0
  136. package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/resolve-secret.mjs +151 -176
  137. package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/rotate-secret.mjs +266 -0
  138. package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/surfaces.mjs +147 -0
  139. package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/validate-config.mjs +224 -0
  140. package/plugins/lisa-cursor/skills/lisa-setup-automations/SKILL.md +69 -0
  141. package/plugins/lisa-cursor/skills/lisa-setup-automations/scripts/generate-workflow.mjs +185 -0
  142. package/plugins/lisa-cursor/skills/lisa-setup-remote-env/SKILL.md +150 -0
  143. package/plugins/lisa-cursor/skills/lisa-setup-remote-env/assets/setup.sh +45 -0
  144. package/plugins/lisa-cursor/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +227 -0
  145. package/plugins/lisa-cursor/skills/lisa-setup-remote-env/scripts/toolchain.mjs +169 -0
  146. package/plugins/lisa-cursor/skills/lisa-setup-remote-env/scripts/verify-remote-env.mjs +186 -0
  147. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  148. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  149. package/plugins/lisa-expo-agy/plugin.json +1 -1
  150. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  151. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  152. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  153. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  154. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  155. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  156. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  157. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  158. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  159. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  160. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  161. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  162. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  163. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  164. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  165. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  166. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  167. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  168. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  169. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  170. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  171. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  172. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  173. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  174. package/plugins/lisa-rails-agy/plugin.json +1 -1
  175. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  176. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  177. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  178. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  179. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  180. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  181. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  182. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  183. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  184. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  185. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  186. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  187. package/plugins/src/base/commands/implement.md +5 -3
  188. package/plugins/src/base/commands/setup/remote-env.md +7 -0
  189. package/plugins/src/base/skills/lisa-atlassian-access/SKILL.md +17 -0
  190. package/plugins/src/base/skills/lisa-automation-status/SKILL.md +23 -0
  191. package/plugins/src/base/skills/lisa-doctor/SKILL.md +33 -0
  192. package/plugins/src/base/skills/lisa-implement/SKILL.md +17 -0
  193. package/plugins/src/base/skills/lisa-notion-access/SKILL.md +17 -0
  194. package/plugins/src/base/skills/lisa-remote-dispatch/SKILL.md +106 -0
  195. package/plugins/src/base/skills/lisa-remote-dispatch/scripts/dispatch.mjs +264 -0
  196. package/plugins/src/base/skills/lisa-secrets-access/SKILL.md +138 -52
  197. package/plugins/src/base/skills/lisa-secrets-access/scripts/doctor-secrets.mjs +217 -0
  198. package/plugins/src/base/skills/lisa-secrets-access/scripts/envfile.mjs +78 -0
  199. package/plugins/src/base/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +105 -0
  200. package/plugins/src/base/skills/lisa-secrets-access/scripts/providers.mjs +240 -0
  201. package/plugins/src/base/skills/lisa-secrets-access/scripts/read-secret-note.mjs +82 -0
  202. package/plugins/src/base/skills/lisa-secrets-access/scripts/resolve-secret.mjs +151 -176
  203. package/plugins/src/base/skills/lisa-secrets-access/scripts/rotate-secret.mjs +266 -0
  204. package/plugins/src/base/skills/lisa-secrets-access/scripts/surfaces.mjs +147 -0
  205. package/plugins/src/base/skills/lisa-secrets-access/scripts/validate-config.mjs +224 -0
  206. package/plugins/src/base/skills/lisa-setup-automations/SKILL.md +69 -0
  207. package/plugins/src/base/skills/lisa-setup-automations/scripts/generate-workflow.mjs +185 -0
  208. package/plugins/src/base/skills/lisa-setup-remote-env/SKILL.md +150 -0
  209. package/plugins/src/base/skills/lisa-setup-remote-env/assets/setup.sh +45 -0
  210. package/plugins/src/base/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +227 -0
  211. package/plugins/src/base/skills/lisa-setup-remote-env/scripts/toolchain.mjs +169 -0
  212. package/plugins/src/base/skills/lisa-setup-remote-env/scripts/verify-remote-env.mjs +186 -0
@@ -0,0 +1,186 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Prove a remote environment is actually configured the way it was meant to be.
4
+ *
5
+ * This runs identically whatever provisioned the environment — an API, a driven
6
+ * browser, or a human pasting emitted config. That is the point: trust comes
7
+ * from the read-back, not from the mechanism, so the weakest provisioning tier
8
+ * ends up as trustworthy as the strongest.
9
+ *
10
+ * Every assertion is made **without printing a value**. Presence, mode, and
11
+ * shape are all checkable without revealing content, and an environment proof
12
+ * that leaks the thing it is proving is not a proof worth having.
13
+ *
14
+ * One rule this encodes the hard way: never verify against a vendor's own UI.
15
+ * A dashboard counter reported zero tasks for an environment that had
16
+ * demonstrably completed one, because the underlying records carried no
17
+ * environment identifier. Assert against durable state instead.
18
+ *
19
+ * Usage:
20
+ * verify-remote-env.mjs
21
+ * @module verify-remote-env
22
+ */
23
+
24
+ import { execFileSync } from "node:child_process";
25
+ import { existsSync, statSync } from "node:fs";
26
+
27
+ import { readRemoteEnvConfig } from "./setup-remote-env.mjs";
28
+ import { extractVersion } from "./toolchain.mjs";
29
+
30
+ /** Collected results, so every check runs before anything reports failure. */
31
+ const results = [];
32
+
33
+ /**
34
+ * Record one assertion.
35
+ * @param {boolean} ok Whether it held.
36
+ * @param {string} label What was checked.
37
+ * @param {string} [detail] Extra context, never a secret value.
38
+ */
39
+ function check(ok, label, detail = "") {
40
+ results.push({ ok, label, detail });
41
+ }
42
+
43
+ /**
44
+ * Assert a path exists with an exact permission mode.
45
+ *
46
+ * The mode is the assertion, not merely existence. A world-readable secrets
47
+ * file is present and wrong, and "present" is what a weaker check would report.
48
+ * @param {string} path Filesystem path.
49
+ * @param {number} mode Expected permission bits.
50
+ * @param {string} label What this path is.
51
+ */
52
+ function checkMode(path, mode, label) {
53
+ if (!existsSync(path)) {
54
+ check(false, label, "absent");
55
+ return;
56
+ }
57
+ const actual = statSync(path).mode & 0o777;
58
+ check(
59
+ actual === mode,
60
+ label,
61
+ actual === mode
62
+ ? `mode ${mode.toString(8)}`
63
+ : `mode ${actual.toString(8)}, expected ${mode.toString(8)}`
64
+ );
65
+ }
66
+
67
+ /**
68
+ * Run a sibling skill's script and capture its output.
69
+ * @param {string[]} args Node arguments.
70
+ * @returns {{ok: boolean, out: string}} Result.
71
+ */
72
+ function node(args) {
73
+ try {
74
+ const out = execFileSync("node", args, {
75
+ encoding: "utf8",
76
+ stdio: ["ignore", "pipe", "pipe"],
77
+ });
78
+ return { ok: true, out: out.trim() };
79
+ } catch (err) {
80
+ return { ok: false, out: String(err.stderr ?? err.message).trim() };
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Assert each declared tool is present at its pinned or minimum version.
86
+ * @param {object} tools Toolchain manifest.
87
+ */
88
+ function verifyToolchain(tools) {
89
+ for (const tool of tools.require ?? []) {
90
+ try {
91
+ const out = execFileSync(tool.name, ["--version"], {
92
+ encoding: "utf8",
93
+ stdio: ["ignore", "pipe", "ignore"],
94
+ });
95
+ check(true, `tool ${tool.name}`, extractVersion(out) ?? "present");
96
+ } catch {
97
+ check(false, `tool ${tool.name}`, "required but not present");
98
+ }
99
+ }
100
+ for (const tool of tools.install ?? []) {
101
+ try {
102
+ const out = execFileSync(tool.name, ["--version"], {
103
+ encoding: "utf8",
104
+ stdio: ["ignore", "pipe", "ignore"],
105
+ });
106
+ const found = extractVersion(out);
107
+ check(
108
+ found === tool.version,
109
+ `tool ${tool.name}`,
110
+ `${found} (pin ${tool.version})`
111
+ );
112
+ } catch {
113
+ check(
114
+ false,
115
+ `tool ${tool.name}`,
116
+ `pinned ${tool.version} but not installed`
117
+ );
118
+ }
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Assert the working tree is clean.
124
+ *
125
+ * A remote environment that starts dirty will carry unrelated changes into
126
+ * whatever it produces, and the resulting diff is no longer attributable to the
127
+ * task that ran.
128
+ */
129
+ function verifyCleanCheckout() {
130
+ try {
131
+ const out = execFileSync("git", ["status", "--porcelain"], {
132
+ encoding: "utf8",
133
+ stdio: ["ignore", "pipe", "ignore"],
134
+ });
135
+ check(
136
+ out.trim() === "",
137
+ "clean checkout",
138
+ out.trim() ? "working tree is dirty" : ""
139
+ );
140
+ } catch {
141
+ check(false, "clean checkout", "not a git repository");
142
+ }
143
+ }
144
+
145
+ function main() {
146
+ const cfg = readRemoteEnvConfig();
147
+ const secretsDir = process.argv[2];
148
+
149
+ verifyToolchain(cfg.tools);
150
+
151
+ const surface = node([
152
+ new URL(
153
+ "../../lisa-secrets-access/scripts/resolve-secret.mjs",
154
+ import.meta.url
155
+ ).pathname,
156
+ "surface",
157
+ ]);
158
+ check(surface.ok, "surface detected", surface.out);
159
+
160
+ if (secretsDir) {
161
+ checkMode(secretsDir, 0o700, "secrets directory");
162
+ checkMode(`${secretsDir}/secrets.env`, 0o600, "values file");
163
+ checkMode(`${secretsDir}/secret-notes.json`, 0o600, "notes file");
164
+ }
165
+
166
+ verifyCleanCheckout();
167
+
168
+ let failed = 0;
169
+ for (const r of results) {
170
+ if (!r.ok) failed += 1;
171
+ console.log(
172
+ ` ${r.ok ? "ok " : "FAIL"} ${r.label.padEnd(28)} ${r.detail}`
173
+ );
174
+ }
175
+ if (failed) throw new Error(`${failed} environment check(s) failed`);
176
+ console.log("\nRemote environment verified without revealing any value.");
177
+ }
178
+
179
+ if (import.meta.url === `file://${process.argv[1]}`) {
180
+ try {
181
+ main();
182
+ } catch (err) {
183
+ console.error(err.message);
184
+ process.exit(1);
185
+ }
186
+ }