@mstar-harness/cli 1.6.1 → 1.8.0
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/dist/mstar-harness.js +242 -52
- package/package.json +2 -2
package/dist/mstar-harness.js
CHANGED
|
@@ -2344,8 +2344,8 @@ var require_commander = __commonJS((exports) => {
|
|
|
2344
2344
|
});
|
|
2345
2345
|
|
|
2346
2346
|
// src/index.ts
|
|
2347
|
-
import
|
|
2348
|
-
import
|
|
2347
|
+
import fs8 from "fs";
|
|
2348
|
+
import path10 from "path";
|
|
2349
2349
|
import { fileURLToPath } from "url";
|
|
2350
2350
|
|
|
2351
2351
|
// ../../node_modules/@inquirer/core/dist/lib/key.js
|
|
@@ -4070,7 +4070,11 @@ import { execFileSync } from "node:child_process";
|
|
|
4070
4070
|
var REPO_URL = "https://github.com/btspoony/mstar-harness.git";
|
|
4071
4071
|
var PLUGIN_NAME = "morning-star-harness";
|
|
4072
4072
|
var HARNESS_REPO_PATH = path3.join(os.homedir(), ".mstar", "harness");
|
|
4073
|
-
var HARNESS_MARKERS = [
|
|
4073
|
+
var HARNESS_MARKERS = [
|
|
4074
|
+
".codex-plugin/plugin.json",
|
|
4075
|
+
".zcode-plugin/plugin.json",
|
|
4076
|
+
".omp-plugin/plugin.json"
|
|
4077
|
+
];
|
|
4074
4078
|
function harnessMarkerPath() {
|
|
4075
4079
|
for (const marker of HARNESS_MARKERS) {
|
|
4076
4080
|
const candidate = path3.join(HARNESS_REPO_PATH, marker);
|
|
@@ -4279,12 +4283,13 @@ var CODEX_AGENT_NAMES = [
|
|
|
4279
4283
|
"writing-specialist",
|
|
4280
4284
|
"prompt-engineer"
|
|
4281
4285
|
];
|
|
4282
|
-
var
|
|
4286
|
+
var CODEX_PROJECT_COMMAND_NAMES = [
|
|
4283
4287
|
"iteration-start",
|
|
4284
4288
|
"iteration-drive",
|
|
4285
|
-
"iteration-loop"
|
|
4289
|
+
"iteration-loop",
|
|
4290
|
+
"codebase-audit"
|
|
4286
4291
|
];
|
|
4287
|
-
var GLOBAL_ITERATION_SKILLS_WARNING = "Codex
|
|
4292
|
+
var GLOBAL_ITERATION_SKILLS_WARNING = "Codex project-scoped commands (iteration-start / iteration-drive / iteration-loop / codebase-audit) are installed as project-local skills under .agents/skills/ only. Global install skips them to avoid polluting other code agents. Re-run with --scope project to enable.";
|
|
4288
4293
|
function globalMarketplacePath() {
|
|
4289
4294
|
return GLOBAL_MARKETPLACE_PATH;
|
|
4290
4295
|
}
|
|
@@ -4400,14 +4405,14 @@ function iterationSkillGitignoreEntry(skillName) {
|
|
|
4400
4405
|
function ensureIterationSkillLinks(dryRun) {
|
|
4401
4406
|
const notes = [];
|
|
4402
4407
|
const projectRoot = resolveProjectRoot();
|
|
4403
|
-
for (const skillName of
|
|
4408
|
+
for (const skillName of CODEX_PROJECT_COMMAND_NAMES) {
|
|
4404
4409
|
const source = iterationCommandSourcePath(skillName);
|
|
4405
4410
|
const linkPath = projectIterationSkillLinkPath(skillName);
|
|
4406
4411
|
notes.push(ensureSymlink(source, linkPath, dryRun));
|
|
4407
4412
|
}
|
|
4408
|
-
const gitignoreEntries =
|
|
4413
|
+
const gitignoreEntries = CODEX_PROJECT_COMMAND_NAMES.map(iterationSkillGitignoreEntry);
|
|
4409
4414
|
notes.push(...appendGitignore(projectRoot, gitignoreEntries, dryRun));
|
|
4410
|
-
notes.push("Installed Codex project-scoped
|
|
4415
|
+
notes.push("Installed Codex project-scoped command skills under .agents/skills/ (iteration-start, iteration-drive, iteration-loop, codebase-audit) — symlinked to harness commands/*.md.");
|
|
4411
4416
|
return notes;
|
|
4412
4417
|
}
|
|
4413
4418
|
function validateIterationSkillLinks() {
|
|
@@ -4416,7 +4421,7 @@ function validateIterationSkillLinks() {
|
|
|
4416
4421
|
const gitignorePath = path4.join(projectRoot, ".gitignore");
|
|
4417
4422
|
const gitignore = fs3.existsSync(gitignorePath) ? fs3.readFileSync(gitignorePath, "utf8") : "";
|
|
4418
4423
|
const lines = gitignore.split(/\r?\n/);
|
|
4419
|
-
for (const skillName of
|
|
4424
|
+
for (const skillName of CODEX_PROJECT_COMMAND_NAMES) {
|
|
4420
4425
|
const source = iterationCommandSourcePath(skillName);
|
|
4421
4426
|
const linkPath = projectIterationSkillLinkPath(skillName);
|
|
4422
4427
|
errors2.push(...validateSymlink(source, linkPath));
|
|
@@ -4578,9 +4583,193 @@ var cursorAdapter = {
|
|
|
4578
4583
|
}
|
|
4579
4584
|
};
|
|
4580
4585
|
|
|
4586
|
+
// src/adapters/omp.ts
|
|
4587
|
+
import fs5 from "node:fs";
|
|
4588
|
+
import path6 from "node:path";
|
|
4589
|
+
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
4590
|
+
var OMP_PLUGIN_MARKER = ".omp-plugin/plugin.json";
|
|
4591
|
+
var CLAUDE_PLUGIN_MARKER = ".claude-plugin/plugin.json";
|
|
4592
|
+
var PACKAGE_NAMES = new Set(["morning-star", PLUGIN_NAME, "github:btspoony/mstar-harness"]);
|
|
4593
|
+
var SKILL_SMOKE = ["mstar-host", "mstar-harness-core", "pm"];
|
|
4594
|
+
var COMMAND_SMOKE = ["iteration-start", "iteration-drive", "iteration-loop", "codebase-audit"];
|
|
4595
|
+
function ompAvailable() {
|
|
4596
|
+
try {
|
|
4597
|
+
execFileSync2("omp", ["--version"], { stdio: "pipe", encoding: "utf8" });
|
|
4598
|
+
return true;
|
|
4599
|
+
} catch {
|
|
4600
|
+
return false;
|
|
4601
|
+
}
|
|
4602
|
+
}
|
|
4603
|
+
function runOmp(args, dryRun) {
|
|
4604
|
+
if (dryRun)
|
|
4605
|
+
return;
|
|
4606
|
+
execFileSync2("omp", args, { stdio: "pipe", encoding: "utf8" });
|
|
4607
|
+
}
|
|
4608
|
+
function listInstalledPlugins() {
|
|
4609
|
+
try {
|
|
4610
|
+
const raw = execFileSync2("omp", ["plugin", "list", "--json"], {
|
|
4611
|
+
stdio: "pipe",
|
|
4612
|
+
encoding: "utf8"
|
|
4613
|
+
});
|
|
4614
|
+
const parsed = JSON.parse(raw);
|
|
4615
|
+
if (Array.isArray(parsed))
|
|
4616
|
+
return parsed;
|
|
4617
|
+
if (parsed && typeof parsed === "object") {
|
|
4618
|
+
const record = parsed;
|
|
4619
|
+
if (Array.isArray(record.plugins)) {
|
|
4620
|
+
return record.plugins;
|
|
4621
|
+
}
|
|
4622
|
+
const entries = [];
|
|
4623
|
+
for (const key of ["npm", "marketplace"]) {
|
|
4624
|
+
const group = record[key];
|
|
4625
|
+
if (Array.isArray(group)) {
|
|
4626
|
+
for (const item of group) {
|
|
4627
|
+
if (item && typeof item === "object")
|
|
4628
|
+
entries.push(item);
|
|
4629
|
+
}
|
|
4630
|
+
}
|
|
4631
|
+
}
|
|
4632
|
+
if (entries.length > 0)
|
|
4633
|
+
return entries;
|
|
4634
|
+
}
|
|
4635
|
+
return [];
|
|
4636
|
+
} catch {
|
|
4637
|
+
return [];
|
|
4638
|
+
}
|
|
4639
|
+
}
|
|
4640
|
+
function findInstalledPlugin(plugins) {
|
|
4641
|
+
return plugins.find((entry) => {
|
|
4642
|
+
const name = typeof entry.name === "string" ? entry.name : "";
|
|
4643
|
+
const pathValue = typeof entry.path === "string" ? entry.path : "";
|
|
4644
|
+
const manifest = entry.manifest && typeof entry.manifest === "object" ? entry.manifest : null;
|
|
4645
|
+
const manifestName = typeof manifest?.name === "string" ? manifest.name : "";
|
|
4646
|
+
if (PACKAGE_NAMES.has(name) || PACKAGE_NAMES.has(manifestName))
|
|
4647
|
+
return true;
|
|
4648
|
+
if (name.includes("morning-star") || manifestName.includes("morning-star"))
|
|
4649
|
+
return true;
|
|
4650
|
+
if (pathValue.includes("mstar-harness") || pathValue.includes(`${path6.sep}morning-star`))
|
|
4651
|
+
return true;
|
|
4652
|
+
return false;
|
|
4653
|
+
});
|
|
4654
|
+
}
|
|
4655
|
+
function validatePluginTree(pluginRoot) {
|
|
4656
|
+
const errors2 = [];
|
|
4657
|
+
for (const marker of [OMP_PLUGIN_MARKER, CLAUDE_PLUGIN_MARKER]) {
|
|
4658
|
+
const markerPath = path6.join(pluginRoot, marker);
|
|
4659
|
+
if (!fs5.existsSync(markerPath)) {
|
|
4660
|
+
errors2.push(`Missing omp plugin marker: ${markerPath}`);
|
|
4661
|
+
}
|
|
4662
|
+
}
|
|
4663
|
+
for (const skill of SKILL_SMOKE) {
|
|
4664
|
+
const skillPath = path6.join(pluginRoot, "skills", skill, "SKILL.md");
|
|
4665
|
+
if (!fs5.existsSync(skillPath))
|
|
4666
|
+
errors2.push(`Missing skill: ${skillPath}`);
|
|
4667
|
+
}
|
|
4668
|
+
for (const command of COMMAND_SMOKE) {
|
|
4669
|
+
const commandPath = path6.join(pluginRoot, "commands", `${command}.md`);
|
|
4670
|
+
if (!fs5.existsSync(commandPath))
|
|
4671
|
+
errors2.push(`Missing command: ${commandPath}`);
|
|
4672
|
+
}
|
|
4673
|
+
const hostRef = path6.join(pluginRoot, "skills", "mstar-host", "references", "omp.md");
|
|
4674
|
+
if (!fs5.existsSync(hostRef))
|
|
4675
|
+
errors2.push(`Missing omp host reference: ${hostRef}`);
|
|
4676
|
+
return errors2;
|
|
4677
|
+
}
|
|
4678
|
+
function runInit2(scope, dryRun) {
|
|
4679
|
+
const notes = ensureLocalHarnessRepo(dryRun);
|
|
4680
|
+
const projectRoot = resolveProjectRoot();
|
|
4681
|
+
if (fs5.existsSync(path6.join(HARNESS_REPO_PATH, ".git"))) {
|
|
4682
|
+
if (dryRun) {
|
|
4683
|
+
notes.push(`Would update local harness repo: git -C ${HARNESS_REPO_PATH} pull --ff-only`);
|
|
4684
|
+
} else {
|
|
4685
|
+
try {
|
|
4686
|
+
execFileSync2("git", ["-C", HARNESS_REPO_PATH, "pull", "--ff-only"], {
|
|
4687
|
+
stdio: "pipe",
|
|
4688
|
+
encoding: "utf8"
|
|
4689
|
+
});
|
|
4690
|
+
notes.push(`Updated local harness repo at ${HARNESS_REPO_PATH}`);
|
|
4691
|
+
} catch (error) {
|
|
4692
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4693
|
+
notes.push(`Warning: could not ff-only pull ${HARNESS_REPO_PATH} (${message})`);
|
|
4694
|
+
}
|
|
4695
|
+
}
|
|
4696
|
+
}
|
|
4697
|
+
if (!ompAvailable()) {
|
|
4698
|
+
notes.push("omp CLI not found on PATH. Install Oh My Pi (`omp`), then re-run init or manually: omp plugin install github:btspoony/mstar-harness");
|
|
4699
|
+
} else {
|
|
4700
|
+
const linkArgs = ["plugin", "link", HARNESS_REPO_PATH];
|
|
4701
|
+
if (scope === "project")
|
|
4702
|
+
linkArgs.push("--scope", "project");
|
|
4703
|
+
if (dryRun) {
|
|
4704
|
+
notes.push(`Would run: omp ${linkArgs.join(" ")}`);
|
|
4705
|
+
} else {
|
|
4706
|
+
try {
|
|
4707
|
+
runOmp(linkArgs, dryRun);
|
|
4708
|
+
notes.push(`Linked local harness into omp plugins (${scope}): omp plugin link ${HARNESS_REPO_PATH}${scope === "project" ? " --scope project" : ""}`);
|
|
4709
|
+
} catch (error) {
|
|
4710
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4711
|
+
notes.push(`omp plugin link failed (${message}). Falling back guidance: omp plugin install github:btspoony/mstar-harness`);
|
|
4712
|
+
try {
|
|
4713
|
+
const installArgs = ["plugin", "install", "github:btspoony/mstar-harness"];
|
|
4714
|
+
if (scope === "project")
|
|
4715
|
+
installArgs.push("--scope", "project");
|
|
4716
|
+
runOmp(installArgs, dryRun);
|
|
4717
|
+
notes.push(`Installed github:btspoony/mstar-harness via omp plugin install (${scope}).`);
|
|
4718
|
+
} catch (installError) {
|
|
4719
|
+
const installMessage = installError instanceof Error ? installError.message : String(installError);
|
|
4720
|
+
notes.push(`omp plugin install also failed: ${installMessage}`);
|
|
4721
|
+
}
|
|
4722
|
+
}
|
|
4723
|
+
}
|
|
4724
|
+
}
|
|
4725
|
+
if (scope === "project") {
|
|
4726
|
+
notes.push(...appendHarnessProjectGitignore(projectRoot, dryRun));
|
|
4727
|
+
notes.push(...appendGitignore(projectRoot, [".omp/plugins/", ".omp/plugin-overrides.json", ".omp/plugins/installed_plugins.json"], dryRun));
|
|
4728
|
+
}
|
|
4729
|
+
notes.push("Verify with: omp plugin list");
|
|
4730
|
+
notes.push("Enter PM with /skill:pm ; commands: /iteration-start /iteration-drive /iteration-loop /codebase-audit");
|
|
4731
|
+
notes.push(`Host adapter: skills/mstar-host/references/omp.md`);
|
|
4732
|
+
notes.push(`Alternate install without CLI link: omp plugin install ${REPO_URL.replace("https://github.com/", "github:").replace(/\.git$/, "")}`);
|
|
4733
|
+
return {
|
|
4734
|
+
location: HARNESS_REPO_PATH,
|
|
4735
|
+
notes
|
|
4736
|
+
};
|
|
4737
|
+
}
|
|
4738
|
+
function runDoctor2(scope) {
|
|
4739
|
+
const errors2 = [];
|
|
4740
|
+
errors2.push(...validateLocalHarnessRepo());
|
|
4741
|
+
errors2.push(...validatePluginTree(HARNESS_REPO_PATH));
|
|
4742
|
+
if (!ompAvailable()) {
|
|
4743
|
+
errors2.push("omp CLI not found on PATH (required for omp target doctor checks).");
|
|
4744
|
+
} else {
|
|
4745
|
+
const plugins = listInstalledPlugins();
|
|
4746
|
+
const installed = findInstalledPlugin(plugins);
|
|
4747
|
+
if (!installed) {
|
|
4748
|
+
errors2.push(`Morning Star plugin not found in \`omp plugin list\` (expected one of: ${[...PACKAGE_NAMES].join(", ")}). Run: mstar-harness init --target omp --scope ${scope}`);
|
|
4749
|
+
} else if (installed.enabled === false) {
|
|
4750
|
+
errors2.push(`Morning Star omp plugin is installed but disabled (${String(installed.name)}).`);
|
|
4751
|
+
}
|
|
4752
|
+
}
|
|
4753
|
+
if (scope === "project") {
|
|
4754
|
+
const projectRoot = resolveProjectRoot();
|
|
4755
|
+
const gitignorePath = path6.join(projectRoot, ".gitignore");
|
|
4756
|
+
const gitignore = fs5.existsSync(gitignorePath) ? fs5.readFileSync(gitignorePath, "utf8") : "";
|
|
4757
|
+
for (const entry of missingHarnessProcessGitignoreEntries(gitignore)) {
|
|
4758
|
+
errors2.push(`Missing .gitignore entry: ${entry}`);
|
|
4759
|
+
}
|
|
4760
|
+
}
|
|
4761
|
+
return { location: HARNESS_REPO_PATH, errors: errors2 };
|
|
4762
|
+
}
|
|
4763
|
+
var ompAdapter = {
|
|
4764
|
+
target: "omp",
|
|
4765
|
+
mode: "install",
|
|
4766
|
+
runInstallInit: (scope, dryRun) => runInit2(scope, dryRun),
|
|
4767
|
+
runInstallDoctor: (scope) => runDoctor2(scope)
|
|
4768
|
+
};
|
|
4769
|
+
|
|
4581
4770
|
// src/adapters/opencode.ts
|
|
4582
4771
|
import os4 from "node:os";
|
|
4583
|
-
import
|
|
4772
|
+
import path7 from "node:path";
|
|
4584
4773
|
var OPENCODE_CONFIG_SCHEMA = "https://opencode.ai/config.json";
|
|
4585
4774
|
var MSTAR_OPENCODE_PLUGIN = "@mstar-harness/opencode@latest";
|
|
4586
4775
|
function isLegacyMorningStarGitPlugin(plugin) {
|
|
@@ -4601,11 +4790,11 @@ function isAnyMstarHarnessOpencodeSlot(plugin) {
|
|
|
4601
4790
|
function resolveOpencodeConfigPath(scope, outputPath) {
|
|
4602
4791
|
if (outputPath && outputPath.trim()) {
|
|
4603
4792
|
const raw = outputPath.trim();
|
|
4604
|
-
return
|
|
4793
|
+
return path7.isAbsolute(raw) ? raw : path7.join(resolveProjectRoot(), raw);
|
|
4605
4794
|
}
|
|
4606
4795
|
if (scope === "global")
|
|
4607
|
-
return
|
|
4608
|
-
return
|
|
4796
|
+
return path7.join(os4.homedir(), ".config", "opencode", "opencode.json");
|
|
4797
|
+
return path7.join(resolveProjectRoot(), "opencode.json");
|
|
4609
4798
|
}
|
|
4610
4799
|
function ensureConfigSchema(config) {
|
|
4611
4800
|
const next = ensureObject(config);
|
|
@@ -4698,9 +4887,9 @@ var opencodeAdapter = {
|
|
|
4698
4887
|
};
|
|
4699
4888
|
|
|
4700
4889
|
// src/adapters/zcode.ts
|
|
4701
|
-
import
|
|
4890
|
+
import fs6 from "node:fs";
|
|
4702
4891
|
import os5 from "node:os";
|
|
4703
|
-
import
|
|
4892
|
+
import path8 from "node:path";
|
|
4704
4893
|
var MARKETPLACE_ID = "mstar-local";
|
|
4705
4894
|
var MARKETPLACE_NAME2 = "mstar-local";
|
|
4706
4895
|
var MARKETPLACE_DESCRIPTION = "Morning Star harness marketplace (GitHub source).";
|
|
@@ -4712,10 +4901,10 @@ var GITHUB_REF = "main";
|
|
|
4712
4901
|
var ZCODE_PLUGIN_MARKER = ".zcode-plugin/plugin.json";
|
|
4713
4902
|
var ZCODE_PLUGIN_CHECKOUT_PROJECT = ".zcode/plugin-checkout";
|
|
4714
4903
|
var ZCODE_AGENT_SMOKE_NAMES = ["fullstack-dev", "qc-specialist"];
|
|
4715
|
-
var ZCODE_PLUGINS_ROOT =
|
|
4716
|
-
var KNOWN_MARKETPLACES_PATH =
|
|
4717
|
-
var MARKETPLACE_DIR =
|
|
4718
|
-
var MARKETPLACE_JSON_PATH =
|
|
4904
|
+
var ZCODE_PLUGINS_ROOT = path8.join(os5.homedir(), ".zcode", "cli", "plugins");
|
|
4905
|
+
var KNOWN_MARKETPLACES_PATH = path8.join(ZCODE_PLUGINS_ROOT, "known_marketplaces.json");
|
|
4906
|
+
var MARKETPLACE_DIR = path8.join(ZCODE_PLUGINS_ROOT, "marketplaces", MARKETPLACE_ID);
|
|
4907
|
+
var MARKETPLACE_JSON_PATH = path8.join(MARKETPLACE_DIR, "marketplace.json");
|
|
4719
4908
|
var GITHUB_SOURCE = { source: "github", repo: GITHUB_REPO, ref: GITHUB_REF };
|
|
4720
4909
|
function nowIso() {
|
|
4721
4910
|
return new Date().toISOString();
|
|
@@ -4771,7 +4960,7 @@ function findMarketplacePlugin(raw) {
|
|
|
4771
4960
|
}
|
|
4772
4961
|
function validateMarketplaceJson() {
|
|
4773
4962
|
const errors2 = [];
|
|
4774
|
-
if (!
|
|
4963
|
+
if (!fs6.existsSync(MARKETPLACE_JSON_PATH)) {
|
|
4775
4964
|
errors2.push(`Missing ZCode marketplace: ${MARKETPLACE_JSON_PATH}`);
|
|
4776
4965
|
return errors2;
|
|
4777
4966
|
}
|
|
@@ -4799,7 +4988,7 @@ function validateMarketplaceJson() {
|
|
|
4799
4988
|
}
|
|
4800
4989
|
function validateKnownMarketplaces() {
|
|
4801
4990
|
const errors2 = [];
|
|
4802
|
-
if (!
|
|
4991
|
+
if (!fs6.existsSync(KNOWN_MARKETPLACES_PATH)) {
|
|
4803
4992
|
errors2.push(`Missing ZCode known_marketplaces.json: ${KNOWN_MARKETPLACES_PATH}`);
|
|
4804
4993
|
return errors2;
|
|
4805
4994
|
}
|
|
@@ -4822,14 +5011,14 @@ function validateKnownMarketplaces() {
|
|
|
4822
5011
|
}
|
|
4823
5012
|
function validatePluginAgents2(pluginRoot) {
|
|
4824
5013
|
const errors2 = [];
|
|
4825
|
-
const agentsDir =
|
|
4826
|
-
if (!
|
|
5014
|
+
const agentsDir = path8.join(pluginRoot, "agents");
|
|
5015
|
+
if (!fs6.existsSync(agentsDir)) {
|
|
4827
5016
|
errors2.push(`Missing plugin agents directory: ${agentsDir}`);
|
|
4828
5017
|
return errors2;
|
|
4829
5018
|
}
|
|
4830
5019
|
for (const agentName of ZCODE_AGENT_SMOKE_NAMES) {
|
|
4831
|
-
const agentPath =
|
|
4832
|
-
if (!
|
|
5020
|
+
const agentPath = path8.join(agentsDir, `${agentName}.md`);
|
|
5021
|
+
if (!fs6.existsSync(agentPath)) {
|
|
4833
5022
|
errors2.push(`Missing plugin agent file: ${agentPath}`);
|
|
4834
5023
|
}
|
|
4835
5024
|
}
|
|
@@ -4842,19 +5031,19 @@ function buildMarketplaceJson() {
|
|
|
4842
5031
|
plugins: [marketplacePluginEntry()]
|
|
4843
5032
|
};
|
|
4844
5033
|
}
|
|
4845
|
-
function
|
|
5034
|
+
function runInit3(scope, dryRun) {
|
|
4846
5035
|
const notes = ensureLocalHarnessRepo(dryRun);
|
|
4847
5036
|
const projectRoot = resolveProjectRoot();
|
|
4848
5037
|
if (scope === "project") {
|
|
4849
|
-
const checkoutPath =
|
|
5038
|
+
const checkoutPath = path8.join(projectRoot, ZCODE_PLUGIN_CHECKOUT_PROJECT);
|
|
4850
5039
|
notes.push(...ensureGitCheckout(REPO_URL, checkoutPath, dryRun));
|
|
4851
5040
|
notes.push(...appendGitignore(projectRoot, [ZCODE_PLUGIN_CHECKOUT_PROJECT], dryRun));
|
|
4852
5041
|
notes.push(...appendHarnessProjectGitignore(projectRoot, dryRun));
|
|
4853
5042
|
notes.push(`Materialized local ZCode plugin checkout at ${ZCODE_PLUGIN_CHECKOUT_PROJECT} for smoke checks (the registered marketplace still points at the github repo).`);
|
|
4854
5043
|
}
|
|
4855
5044
|
if (!dryRun) {
|
|
4856
|
-
if (!
|
|
4857
|
-
|
|
5045
|
+
if (!fs6.existsSync(MARKETPLACE_DIR))
|
|
5046
|
+
fs6.mkdirSync(MARKETPLACE_DIR, { recursive: true });
|
|
4858
5047
|
writeJson(MARKETPLACE_JSON_PATH, buildMarketplaceJson());
|
|
4859
5048
|
}
|
|
4860
5049
|
notes.push(`Wrote ZCode marketplace: ${MARKETPLACE_JSON_PATH}`);
|
|
@@ -4869,15 +5058,15 @@ function runInit2(scope, dryRun) {
|
|
|
4869
5058
|
notes
|
|
4870
5059
|
};
|
|
4871
5060
|
}
|
|
4872
|
-
function
|
|
5061
|
+
function runDoctor3(scope) {
|
|
4873
5062
|
const errors2 = [];
|
|
4874
5063
|
errors2.push(...validateLocalHarnessRepo());
|
|
4875
5064
|
if (scope === "project") {
|
|
4876
5065
|
const projectRoot = resolveProjectRoot();
|
|
4877
|
-
const checkoutPath =
|
|
5066
|
+
const checkoutPath = path8.join(projectRoot, ZCODE_PLUGIN_CHECKOUT_PROJECT);
|
|
4878
5067
|
errors2.push(...validateGitCheckout(checkoutPath, ZCODE_PLUGIN_MARKER));
|
|
4879
|
-
const gitignorePath =
|
|
4880
|
-
const gitignore =
|
|
5068
|
+
const gitignorePath = path8.join(projectRoot, ".gitignore");
|
|
5069
|
+
const gitignore = fs6.existsSync(gitignorePath) ? fs6.readFileSync(gitignorePath, "utf8") : "";
|
|
4881
5070
|
if (!gitignore.split(/\r?\n/).includes(ZCODE_PLUGIN_CHECKOUT_PROJECT)) {
|
|
4882
5071
|
errors2.push(`Missing .gitignore entry: ${ZCODE_PLUGIN_CHECKOUT_PROJECT}`);
|
|
4883
5072
|
}
|
|
@@ -4895,8 +5084,8 @@ function runDoctor2(scope) {
|
|
|
4895
5084
|
var zcodeAdapter = {
|
|
4896
5085
|
target: "zcode",
|
|
4897
5086
|
mode: "install",
|
|
4898
|
-
runInstallInit: (scope, dryRun) =>
|
|
4899
|
-
runInstallDoctor: (scope) =>
|
|
5087
|
+
runInstallInit: (scope, dryRun) => runInit3(scope, dryRun),
|
|
5088
|
+
runInstallDoctor: (scope) => runDoctor3(scope)
|
|
4900
5089
|
};
|
|
4901
5090
|
|
|
4902
5091
|
// src/adapters/index.ts
|
|
@@ -4904,7 +5093,8 @@ var adapters = {
|
|
|
4904
5093
|
opencode: opencodeAdapter,
|
|
4905
5094
|
cursor: cursorAdapter,
|
|
4906
5095
|
codex: codexAdapter,
|
|
4907
|
-
zcode: zcodeAdapter
|
|
5096
|
+
zcode: zcodeAdapter,
|
|
5097
|
+
omp: ompAdapter
|
|
4908
5098
|
};
|
|
4909
5099
|
function getAdapter(target) {
|
|
4910
5100
|
const adapter = adapters[target];
|
|
@@ -4914,20 +5104,20 @@ function getAdapter(target) {
|
|
|
4914
5104
|
}
|
|
4915
5105
|
|
|
4916
5106
|
// src/types.ts
|
|
4917
|
-
var SUPPORTED_TARGETS = ["opencode", "cursor", "codex", "zcode"];
|
|
5107
|
+
var SUPPORTED_TARGETS = ["opencode", "cursor", "codex", "zcode", "omp"];
|
|
4918
5108
|
|
|
4919
5109
|
// src/utils.ts
|
|
4920
|
-
import
|
|
4921
|
-
import
|
|
5110
|
+
import fs7 from "node:fs";
|
|
5111
|
+
import path9 from "node:path";
|
|
4922
5112
|
function parseCsv(raw) {
|
|
4923
5113
|
if (!raw)
|
|
4924
5114
|
return;
|
|
4925
5115
|
return raw.split(",").map((item) => item.trim()).filter(Boolean);
|
|
4926
5116
|
}
|
|
4927
5117
|
function readJson2(filePath) {
|
|
4928
|
-
if (!
|
|
5118
|
+
if (!fs7.existsSync(filePath))
|
|
4929
5119
|
return {};
|
|
4930
|
-
const content =
|
|
5120
|
+
const content = fs7.readFileSync(filePath, "utf8").trim();
|
|
4931
5121
|
if (!content)
|
|
4932
5122
|
return {};
|
|
4933
5123
|
try {
|
|
@@ -4937,18 +5127,18 @@ function readJson2(filePath) {
|
|
|
4937
5127
|
}
|
|
4938
5128
|
}
|
|
4939
5129
|
function writeJson2(filePath, value) {
|
|
4940
|
-
const parent =
|
|
4941
|
-
if (!
|
|
4942
|
-
|
|
4943
|
-
|
|
5130
|
+
const parent = path9.dirname(filePath);
|
|
5131
|
+
if (!fs7.existsSync(parent))
|
|
5132
|
+
fs7.mkdirSync(parent, { recursive: true });
|
|
5133
|
+
fs7.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}
|
|
4944
5134
|
`, "utf8");
|
|
4945
5135
|
}
|
|
4946
5136
|
|
|
4947
5137
|
// src/index.ts
|
|
4948
|
-
var packageJsonPath =
|
|
5138
|
+
var packageJsonPath = path10.resolve(path10.dirname(fileURLToPath(import.meta.url)), "../package.json");
|
|
4949
5139
|
var packageVersion = (() => {
|
|
4950
5140
|
try {
|
|
4951
|
-
const parsed = JSON.parse(
|
|
5141
|
+
const parsed = JSON.parse(fs8.readFileSync(packageJsonPath, "utf8"));
|
|
4952
5142
|
return parsed.version || "0.0.0";
|
|
4953
5143
|
} catch {
|
|
4954
5144
|
return "0.0.0";
|
|
@@ -4986,7 +5176,7 @@ function resolveExplicitModelAssignments(options) {
|
|
|
4986
5176
|
others: allow("other-models", parseCsv(options.otherModels), 3, true)
|
|
4987
5177
|
});
|
|
4988
5178
|
}
|
|
4989
|
-
async function
|
|
5179
|
+
async function runInit4(options) {
|
|
4990
5180
|
const target = options.target || (options.yes ? "opencode" : await pickTargetInteractive());
|
|
4991
5181
|
const scope = options.scope || "project";
|
|
4992
5182
|
const adapter = getAdapter(target);
|
|
@@ -5049,7 +5239,7 @@ async function runInit3(options) {
|
|
|
5049
5239
|
}
|
|
5050
5240
|
}
|
|
5051
5241
|
}
|
|
5052
|
-
function
|
|
5242
|
+
function runDoctor4(options) {
|
|
5053
5243
|
const target = options.target || "opencode";
|
|
5054
5244
|
const adapter = getAdapter(target);
|
|
5055
5245
|
const scope = options.scope || "project";
|
|
@@ -5094,10 +5284,10 @@ function runDoctor3(options) {
|
|
|
5094
5284
|
}
|
|
5095
5285
|
program2.name("mstar-harness").description("Morning Star harness CLI for target-based agent bootstrap").version(packageVersion);
|
|
5096
5286
|
program2.command("init").description("Interactive/non-interactive setup for target agent bootstrap").option("-y, --yes", "Non-interactive mode").option("--target <target>", "Install target", "opencode").option("--scope <scope>", "Config scope: global|project (default: project)").option("--output <path>", "Config file path override, relative to project root").option("--dry-run", "Preview result without writing config").option("--pm-model <model>", "Optional: model for project-manager (advanced override)").option("--strategic-models <a,b,c>", "Optional: models for architect/product-manager/prompt-engineer").option("--dev-models <a,b,c>", "Optional: models for fullstack-dev/fullstack-dev-2/frontend-dev").option("--qc-models <a,b,c>", "Optional: models for qc trio").option("--other-models <a,b,c>", "Optional: models for remaining roles").action(async (options) => {
|
|
5097
|
-
await
|
|
5287
|
+
await runInit4(options);
|
|
5098
5288
|
});
|
|
5099
5289
|
program2.command("doctor").description("Validate Morning Star setup for a target agent config").option("--target <target>", "Target agent for doctor checks", "opencode").option("--scope <scope>", "Config scope: global|project", "project").option("--output <path>", "Config file path override, relative to project root").action((options) => {
|
|
5100
|
-
|
|
5290
|
+
runDoctor4(options);
|
|
5101
5291
|
});
|
|
5102
5292
|
program2.parseAsync(process.argv).catch((error) => {
|
|
5103
5293
|
console.error(import_picocolors.default.red(`Setup failed: ${error.message}`));
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mstar-harness/cli",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Morning Star harness installer CLI (OpenCode, Cursor, Codex).",
|
|
3
|
+
"version": "1.8.0",
|
|
4
|
+
"description": "Morning Star harness installer CLI (OpenCode, Cursor, Codex, ZCode, omp).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|