@bx-h/meta-flow 0.1.1 → 0.1.2
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 +8 -0
- package/README.md +2 -2
- package/bin/meta-flow.js +3 -1
- package/marketplace/marketplace.json +2 -1
- package/package.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/templates/milestone-plan.json +9 -3
- package/plugin/templates/task-list.json +9 -3
- package/plugin/templates/task-spec.json +9 -3
- package/src/cli/commands/doctor.js +63 -8
- package/src/cli/commands/verify.js +27 -12
- package/src/cli/lib/marketplace.js +7 -2
- package/src/cli/lib/plugin.js +3 -2
- package/src/cli/lib/support.js +41 -7
- package/src/cli/lib/version.js +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.2
|
|
4
|
+
|
|
5
|
+
- Make installed JSON templates pass their matching validation scripts.
|
|
6
|
+
- Add template validation to `verify` and `doctor`.
|
|
7
|
+
- Propagate command return codes through the CLI entrypoint.
|
|
8
|
+
- Tighten `doctor` checks for marketplace, plugin version, support scripts, and CLI-visible failures.
|
|
9
|
+
- Make the release workflow skip npm publish when the tag version already exists.
|
|
10
|
+
|
|
3
11
|
## 0.1.1
|
|
4
12
|
|
|
5
13
|
- Install `meta-flow` into `.agents/skills/meta-flow` so `$meta-flow` can be discovered directly.
|
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ meta-flow install --scope repo
|
|
|
26
26
|
Pinned version:
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
|
-
npx @bx-h/meta-flow@0.1.
|
|
29
|
+
npx @bx-h/meta-flow@0.1.2 install --scope repo
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
## Quick Start
|
|
@@ -165,7 +165,7 @@ meta-flow uninstall --scope repo --dry-run
|
|
|
165
165
|
You can also distribute the plugin through a Codex marketplace entry:
|
|
166
166
|
|
|
167
167
|
```bash
|
|
168
|
-
codex plugin marketplace add bx-h/meta-flow --ref v0.1.
|
|
168
|
+
codex plugin marketplace add bx-h/meta-flow --ref v0.1.2
|
|
169
169
|
```
|
|
170
170
|
|
|
171
171
|
The npm installer still matters because it also materializes custom agent TOML files and validation scripts.
|
package/bin/meta-flow.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { main } from "../src/cli/index.js";
|
|
3
3
|
|
|
4
|
-
main(process.argv.slice(2)).
|
|
4
|
+
main(process.argv.slice(2)).then((code) => {
|
|
5
|
+
process.exitCode = code;
|
|
6
|
+
}).catch((error) => {
|
|
5
7
|
console.error(error?.message || String(error));
|
|
6
8
|
process.exitCode = 1;
|
|
7
9
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bx-h/meta-flow",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "A Codex-native workflow for clarified goals, reviewed proposals, adjudicated plans, task-level execution, verification, and direction-aware iteration.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -4,10 +4,16 @@
|
|
|
4
4
|
{
|
|
5
5
|
"id": "M1",
|
|
6
6
|
"objective": "string",
|
|
7
|
-
"scope": [
|
|
7
|
+
"scope": [
|
|
8
|
+
"string"
|
|
9
|
+
],
|
|
8
10
|
"out_of_scope": [],
|
|
9
|
-
"acceptance_checks": [
|
|
10
|
-
|
|
11
|
+
"acceptance_checks": [
|
|
12
|
+
"string"
|
|
13
|
+
],
|
|
14
|
+
"expected_outputs": [
|
|
15
|
+
"string"
|
|
16
|
+
],
|
|
11
17
|
"risk": "medium",
|
|
12
18
|
"status": "pending"
|
|
13
19
|
}
|
|
@@ -6,11 +6,17 @@
|
|
|
6
6
|
"id": "T1",
|
|
7
7
|
"objective": "string",
|
|
8
8
|
"inputs": [],
|
|
9
|
-
"expected_outputs": [
|
|
10
|
-
|
|
9
|
+
"expected_outputs": [
|
|
10
|
+
"string"
|
|
11
|
+
],
|
|
12
|
+
"allowed_files": [
|
|
13
|
+
"path-or-glob"
|
|
14
|
+
],
|
|
11
15
|
"forbidden_files": [],
|
|
12
16
|
"allowed_commands": [],
|
|
13
|
-
"acceptance_checks": [
|
|
17
|
+
"acceptance_checks": [
|
|
18
|
+
"string"
|
|
19
|
+
],
|
|
14
20
|
"dependencies": [],
|
|
15
21
|
"risk": "medium",
|
|
16
22
|
"repair_attempts": 0,
|
|
@@ -4,11 +4,17 @@
|
|
|
4
4
|
"concrete_task_id": "T1",
|
|
5
5
|
"objective": "string",
|
|
6
6
|
"inputs": [],
|
|
7
|
-
"expected_outputs": [
|
|
8
|
-
|
|
7
|
+
"expected_outputs": [
|
|
8
|
+
"string"
|
|
9
|
+
],
|
|
10
|
+
"allowed_files": [
|
|
11
|
+
"path-or-glob"
|
|
12
|
+
],
|
|
9
13
|
"forbidden_files": [],
|
|
10
14
|
"allowed_commands": [],
|
|
11
|
-
"acceptance_checks": [
|
|
15
|
+
"acceptance_checks": [
|
|
16
|
+
"string"
|
|
17
|
+
],
|
|
12
18
|
"dependencies": [],
|
|
13
19
|
"risk": "medium",
|
|
14
20
|
"repair_attempts": 0,
|
|
@@ -6,9 +6,11 @@ import { AGENT_FILES, validateAgentTemplate } from "../lib/agents.js";
|
|
|
6
6
|
import { inspectCodexConfig } from "../lib/codex_config.js";
|
|
7
7
|
import { pathExists, readJsonOrDefault } from "../lib/fs_safe.js";
|
|
8
8
|
import { createLogger } from "../lib/logger.js";
|
|
9
|
+
import { marketplaceEntry } from "../lib/marketplace.js";
|
|
9
10
|
import { resolveTargets, sampleTaskRoot } from "../lib/paths.js";
|
|
10
11
|
import { validateInstalledSkill } from "../lib/skill.js";
|
|
11
|
-
import { validateSupportFiles } from "../lib/support.js";
|
|
12
|
+
import { HELP_SCRIPT_FILES, validateSupportFiles } from "../lib/support.js";
|
|
13
|
+
import { META_FLOW_VERSION } from "../lib/version.js";
|
|
12
14
|
|
|
13
15
|
export function doctorHelp() {
|
|
14
16
|
return `Usage: meta-flow doctor --scope repo|user [--target <path>] [--verbose]`;
|
|
@@ -35,6 +37,7 @@ export async function runDoctor(argv = []) {
|
|
|
35
37
|
results.push(await checkAgents(targets));
|
|
36
38
|
results.push(await checkConfig(targets));
|
|
37
39
|
results.push(await checkPythonScripts(targets));
|
|
40
|
+
results.push(await checkInstalledTemplates(targets));
|
|
38
41
|
results.push(await checkSampleTask(targets));
|
|
39
42
|
|
|
40
43
|
for (const result of results) {
|
|
@@ -62,6 +65,9 @@ async function checkPlugin(targets) {
|
|
|
62
65
|
if (manifest.name !== "meta-flow") {
|
|
63
66
|
return { level: "FAIL", title: "plugin manifest invalid", message: "Expected name=meta-flow." };
|
|
64
67
|
}
|
|
68
|
+
if (manifest.version !== META_FLOW_VERSION) {
|
|
69
|
+
return { level: "FAIL", title: "plugin manifest version mismatch", message: `Expected version=${META_FLOW_VERSION}.` };
|
|
70
|
+
}
|
|
65
71
|
if (!(await pathExists(skillPath))) {
|
|
66
72
|
return { level: "FAIL", title: "SKILL.md missing", message: "Re-run install." };
|
|
67
73
|
}
|
|
@@ -99,9 +105,35 @@ async function checkMarketplace(targets) {
|
|
|
99
105
|
if (!entry) {
|
|
100
106
|
return { level: "FAIL", title: "marketplace entry missing", message: "Run install to add meta-flow entry." };
|
|
101
107
|
}
|
|
108
|
+
const expected = marketplaceEntry(targets);
|
|
109
|
+
const errors = [];
|
|
110
|
+
if (entry.version !== expected.version) {
|
|
111
|
+
errors.push(`version expected ${expected.version}, got ${entry.version ?? "missing"}`);
|
|
112
|
+
}
|
|
113
|
+
if (entry.source?.source !== expected.source.source) {
|
|
114
|
+
errors.push(`source.source expected ${expected.source.source}`);
|
|
115
|
+
}
|
|
116
|
+
if (entry.source?.path !== expected.source.path) {
|
|
117
|
+
errors.push(`source.path expected ${expected.source.path}, got ${entry.source?.path ?? "missing"}`);
|
|
118
|
+
}
|
|
119
|
+
const pluginPath = resolveMarketplacePluginPath(targets, entry);
|
|
120
|
+
if (!pluginPath || !(await pathExists(path.join(pluginPath, ".codex-plugin", "plugin.json")))) {
|
|
121
|
+
errors.push("source.path does not point to an installed plugin manifest");
|
|
122
|
+
}
|
|
123
|
+
if (errors.length) {
|
|
124
|
+
return { level: "FAIL", title: "marketplace entry invalid", message: errors.join("; ") };
|
|
125
|
+
}
|
|
102
126
|
return { level: "PASS", title: "marketplace entry present" };
|
|
103
127
|
}
|
|
104
128
|
|
|
129
|
+
function resolveMarketplacePluginPath(targets, entry) {
|
|
130
|
+
const sourcePath = entry?.source?.path;
|
|
131
|
+
if (!sourcePath || typeof sourcePath !== "string") {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
return path.isAbsolute(sourcePath) ? sourcePath : path.resolve(targets.target, sourcePath);
|
|
135
|
+
}
|
|
136
|
+
|
|
105
137
|
async function checkAgents(targets) {
|
|
106
138
|
const missing = [];
|
|
107
139
|
const invalid = [];
|
|
@@ -139,17 +171,40 @@ async function checkConfig(targets) {
|
|
|
139
171
|
|
|
140
172
|
async function checkPythonScripts(targets) {
|
|
141
173
|
const scriptsDir = targets.scriptsTarget;
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
174
|
+
const python = resolvePython();
|
|
175
|
+
for (const fileName of HELP_SCRIPT_FILES) {
|
|
176
|
+
const scriptPath = path.join(scriptsDir, fileName);
|
|
177
|
+
if (!(await pathExists(scriptPath))) {
|
|
178
|
+
return { level: "FAIL", title: "Python scripts missing", message: `Missing ${scriptPath}` };
|
|
179
|
+
}
|
|
180
|
+
const result = spawnSync(python, [scriptPath, "--help"], pythonOptions());
|
|
181
|
+
if (result.status !== 0) {
|
|
182
|
+
return { level: "FAIL", title: "Python scripts not runnable", message: `${fileName}: ${result.stderr || result.stdout}` };
|
|
183
|
+
}
|
|
149
184
|
}
|
|
150
185
|
return { level: "PASS", title: "Python scripts runnable" };
|
|
151
186
|
}
|
|
152
187
|
|
|
188
|
+
async function checkInstalledTemplates(targets) {
|
|
189
|
+
const python = resolvePython();
|
|
190
|
+
const scripts = targets.scriptsTarget;
|
|
191
|
+
const templates = targets.templatesTarget;
|
|
192
|
+
const runs = [
|
|
193
|
+
[path.join(scripts, "validate_goal_contract.py"), path.join(templates, "goal-contract.json")],
|
|
194
|
+
[path.join(scripts, "validate_adjudication.py"), path.join(templates, "adjudication-report.json")],
|
|
195
|
+
[path.join(scripts, "validate_milestone_plan.py"), path.join(templates, "milestone-plan.json")],
|
|
196
|
+
[path.join(scripts, "validate_task_list.py"), path.join(templates, "task-list.json")],
|
|
197
|
+
[path.join(scripts, "validate_task_verification.py"), path.join(templates, "task-verification-report.json")]
|
|
198
|
+
];
|
|
199
|
+
for (const args of runs) {
|
|
200
|
+
const result = spawnSync(python, args, pythonOptions());
|
|
201
|
+
if (result.status !== 0) {
|
|
202
|
+
return { level: "FAIL", title: "installed templates invalid", message: result.stderr || result.stdout };
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return { level: "PASS", title: "installed templates valid" };
|
|
206
|
+
}
|
|
207
|
+
|
|
153
208
|
async function checkSampleTask(targets) {
|
|
154
209
|
if (!(await pathExists(sampleTaskRoot))) {
|
|
155
210
|
return { level: "WARN", title: "sample task unavailable", message: "Package examples are not present." };
|
|
@@ -9,6 +9,8 @@ import { runInstall } from "./install.js";
|
|
|
9
9
|
import { runUninstall } from "./uninstall.js";
|
|
10
10
|
import { validatePlugin } from "../lib/plugin.js";
|
|
11
11
|
import { packageRoot, pluginSource, sampleTaskRoot } from "../lib/paths.js";
|
|
12
|
+
import { HELP_SCRIPT_FILES } from "../lib/support.js";
|
|
13
|
+
import { META_FLOW_VERSION, PACKAGE_NAME } from "../lib/version.js";
|
|
12
14
|
|
|
13
15
|
export async function runVerify(argv = []) {
|
|
14
16
|
const lintOnly = argv.includes("--lint-only");
|
|
@@ -22,6 +24,7 @@ export async function runVerify(argv = []) {
|
|
|
22
24
|
checks.push(await checkPlugin());
|
|
23
25
|
checks.push(await checkAgents());
|
|
24
26
|
checks.push(await checkPythonHelp());
|
|
27
|
+
checks.push(await checkTemplates());
|
|
25
28
|
checks.push(await checkSampleTask());
|
|
26
29
|
checks.push(await checkDryRun());
|
|
27
30
|
checks.push(await checkInstallUninstallSimulation());
|
|
@@ -32,7 +35,8 @@ export async function runVerify(argv = []) {
|
|
|
32
35
|
async function checkPackageJson() {
|
|
33
36
|
const packageJson = JSON.parse(await fs.readFile(path.join(packageRoot, "package.json"), "utf8"));
|
|
34
37
|
const errors = [];
|
|
35
|
-
if (packageJson.name !==
|
|
38
|
+
if (packageJson.name !== PACKAGE_NAME) errors.push("unexpected package name");
|
|
39
|
+
if (packageJson.version !== META_FLOW_VERSION) errors.push(`unexpected package version: ${packageJson.version}`);
|
|
36
40
|
if (packageJson.scripts?.postinstall) errors.push("postinstall must not exist");
|
|
37
41
|
if (packageJson.bin?.["meta-flow"] !== "bin/meta-flow.js") errors.push("bin meta-flow is invalid");
|
|
38
42
|
if (packageJson.type !== "module") errors.push("type must be module");
|
|
@@ -65,19 +69,9 @@ async function checkAgents() {
|
|
|
65
69
|
}
|
|
66
70
|
|
|
67
71
|
async function checkPythonHelp() {
|
|
68
|
-
const scripts = [
|
|
69
|
-
"new_task.py",
|
|
70
|
-
"validate_goal_contract.py",
|
|
71
|
-
"aggregate_reviews.py",
|
|
72
|
-
"validate_adjudication.py",
|
|
73
|
-
"validate_milestone_plan.py",
|
|
74
|
-
"validate_task_list.py",
|
|
75
|
-
"validate_task_verification.py",
|
|
76
|
-
"status.py"
|
|
77
|
-
];
|
|
78
72
|
const python = resolvePython();
|
|
79
73
|
const errors = [];
|
|
80
|
-
for (const script of
|
|
74
|
+
for (const script of HELP_SCRIPT_FILES) {
|
|
81
75
|
const run = spawnSync(python, [path.join(pluginSource, "scripts", script), "--help"], pythonOptions());
|
|
82
76
|
if (run.status !== 0) {
|
|
83
77
|
errors.push(`${script} --help failed: ${run.stderr || run.stdout}`);
|
|
@@ -86,6 +80,27 @@ async function checkPythonHelp() {
|
|
|
86
80
|
return result("Python script --help", errors);
|
|
87
81
|
}
|
|
88
82
|
|
|
83
|
+
async function checkTemplates() {
|
|
84
|
+
const python = resolvePython();
|
|
85
|
+
const scripts = path.join(pluginSource, "scripts");
|
|
86
|
+
const templates = path.join(pluginSource, "templates");
|
|
87
|
+
const runs = [
|
|
88
|
+
[path.join(scripts, "validate_goal_contract.py"), path.join(templates, "goal-contract.json")],
|
|
89
|
+
[path.join(scripts, "validate_adjudication.py"), path.join(templates, "adjudication-report.json")],
|
|
90
|
+
[path.join(scripts, "validate_milestone_plan.py"), path.join(templates, "milestone-plan.json")],
|
|
91
|
+
[path.join(scripts, "validate_task_list.py"), path.join(templates, "task-list.json")],
|
|
92
|
+
[path.join(scripts, "validate_task_verification.py"), path.join(templates, "task-verification-report.json")]
|
|
93
|
+
];
|
|
94
|
+
const errors = [];
|
|
95
|
+
for (const args of runs) {
|
|
96
|
+
const run = spawnSync(python, args, pythonOptions());
|
|
97
|
+
if (run.status !== 0) {
|
|
98
|
+
errors.push(`${path.basename(args[1])} failed: ${run.stderr || run.stdout}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return result("templates validate against scripts", errors);
|
|
102
|
+
}
|
|
103
|
+
|
|
89
104
|
async function checkSampleTask() {
|
|
90
105
|
const python = resolvePython();
|
|
91
106
|
const tmp = await fs.mkdtemp(path.join(os.tmpdir(), "meta-flow-verify-"));
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import { readJsonOrDefault, writeJsonPretty } from "./fs_safe.js";
|
|
2
|
+
import { pathExists, readJsonOrDefault, writeJsonPretty } from "./fs_safe.js";
|
|
3
3
|
import { repoMarketplacePath } from "./paths.js";
|
|
4
|
+
import { META_FLOW_VERSION } from "./version.js";
|
|
4
5
|
|
|
5
6
|
export function marketplaceEntry(targets) {
|
|
6
7
|
return {
|
|
7
8
|
name: "meta-flow",
|
|
8
|
-
version:
|
|
9
|
+
version: META_FLOW_VERSION,
|
|
9
10
|
source: {
|
|
10
11
|
source: "local",
|
|
11
12
|
path: targets.scope === "repo" ? repoMarketplacePath() : targets.pluginTarget
|
|
@@ -58,6 +59,9 @@ export async function updateMarketplace(targets, options = {}) {
|
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
export async function uninstallMarketplace(targets, options = {}) {
|
|
62
|
+
if (!(await pathExists(targets.marketplaceTarget))) {
|
|
63
|
+
return { updated: false, skipped: true };
|
|
64
|
+
}
|
|
61
65
|
const current = await readJsonOrDefault(targets.marketplaceTarget, {
|
|
62
66
|
name: "meta-flow-marketplace",
|
|
63
67
|
interface: { displayName: "Meta Flow Marketplace" },
|
|
@@ -65,6 +69,7 @@ export async function uninstallMarketplace(targets, options = {}) {
|
|
|
65
69
|
});
|
|
66
70
|
const next = removeMarketplaceEntry(current);
|
|
67
71
|
await writeJsonPretty(targets.marketplaceTarget, next, options);
|
|
72
|
+
return { updated: true, skipped: false };
|
|
68
73
|
}
|
|
69
74
|
|
|
70
75
|
export function describeMarketplace(targets) {
|
package/src/cli/lib/plugin.js
CHANGED
|
@@ -2,6 +2,7 @@ import fs from "node:fs/promises";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { backupIfExists, copyDirSafe, pathExists, removeDirSafe } from "./fs_safe.js";
|
|
4
4
|
import { pluginSource } from "./paths.js";
|
|
5
|
+
import { META_FLOW_VERSION } from "./version.js";
|
|
5
6
|
|
|
6
7
|
async function isMetaFlowPlugin(dir) {
|
|
7
8
|
try {
|
|
@@ -47,8 +48,8 @@ export async function validatePlugin(root = pluginSource) {
|
|
|
47
48
|
if (manifest.name !== "meta-flow") {
|
|
48
49
|
errors.push("plugin manifest name must be meta-flow");
|
|
49
50
|
}
|
|
50
|
-
if (manifest.version !==
|
|
51
|
-
errors.push(
|
|
51
|
+
if (manifest.version !== META_FLOW_VERSION) {
|
|
52
|
+
errors.push(`plugin manifest version must be ${META_FLOW_VERSION}`);
|
|
52
53
|
}
|
|
53
54
|
if (!/^---\n[\s\S]*?name:\s*meta-flow[\s\S]*?---/m.test(skill)) {
|
|
54
55
|
errors.push("SKILL.md frontmatter must contain name: meta-flow");
|
package/src/cli/lib/support.js
CHANGED
|
@@ -3,6 +3,39 @@ import { hasManagedMarker, installManagedDir, uninstallManagedDir } from "./mana
|
|
|
3
3
|
import { pathExists } from "./fs_safe.js";
|
|
4
4
|
import { scriptsSource, templatesSource } from "./paths.js";
|
|
5
5
|
|
|
6
|
+
export const REQUIRED_SCRIPT_FILES = [
|
|
7
|
+
"_common.py",
|
|
8
|
+
"aggregate_reviews.py",
|
|
9
|
+
"new_task.py",
|
|
10
|
+
"status.py",
|
|
11
|
+
"validate_adjudication.py",
|
|
12
|
+
"validate_goal_contract.py",
|
|
13
|
+
"validate_milestone_plan.py",
|
|
14
|
+
"validate_task_list.py",
|
|
15
|
+
"validate_task_verification.py"
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
export const HELP_SCRIPT_FILES = REQUIRED_SCRIPT_FILES.filter((fileName) => fileName !== "_common.py");
|
|
19
|
+
|
|
20
|
+
export const REQUIRED_TEMPLATE_FILES = [
|
|
21
|
+
"adjudication-report.json",
|
|
22
|
+
"direction-evaluation.json",
|
|
23
|
+
"final-report.md",
|
|
24
|
+
"goal-contract.json",
|
|
25
|
+
"milestone-plan.json",
|
|
26
|
+
"proposal-summary.md",
|
|
27
|
+
"proposal.md",
|
|
28
|
+
"questioning-report.json",
|
|
29
|
+
"raw-request.md",
|
|
30
|
+
"review-aggregate.json",
|
|
31
|
+
"reviewer-report.json",
|
|
32
|
+
"state.json",
|
|
33
|
+
"task-execution-report.json",
|
|
34
|
+
"task-list.json",
|
|
35
|
+
"task-spec.json",
|
|
36
|
+
"task-verification-report.json"
|
|
37
|
+
];
|
|
38
|
+
|
|
6
39
|
export async function installSupportFiles(targets, options = {}) {
|
|
7
40
|
const scripts = await installManagedDir(scriptsSource, targets.scriptsTarget, options);
|
|
8
41
|
const templates = await installManagedDir(templatesSource, targets.templatesTarget, options);
|
|
@@ -16,14 +49,15 @@ export async function uninstallSupportFiles(targets, options = {}) {
|
|
|
16
49
|
}
|
|
17
50
|
|
|
18
51
|
export async function validateSupportFiles(targets) {
|
|
19
|
-
const required = [
|
|
20
|
-
path.join(targets.scriptsTarget, "new_task.py"),
|
|
21
|
-
path.join(targets.scriptsTarget, "validate_goal_contract.py"),
|
|
22
|
-
path.join(targets.templatesTarget, "state.json"),
|
|
23
|
-
path.join(targets.templatesTarget, "goal-contract.json")
|
|
24
|
-
];
|
|
25
52
|
const errors = [];
|
|
26
|
-
for (const
|
|
53
|
+
for (const fileName of REQUIRED_SCRIPT_FILES) {
|
|
54
|
+
const filePath = path.join(targets.scriptsTarget, fileName);
|
|
55
|
+
if (!(await pathExists(filePath))) {
|
|
56
|
+
errors.push(`missing ${filePath}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
for (const fileName of REQUIRED_TEMPLATE_FILES) {
|
|
60
|
+
const filePath = path.join(targets.templatesTarget, fileName);
|
|
27
61
|
if (!(await pathExists(filePath))) {
|
|
28
62
|
errors.push(`missing ${filePath}`);
|
|
29
63
|
}
|