@mstar-harness/cli 3.6.0-alpha.2 → 3.6.0-alpha.3

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 (2) hide show
  1. package/dist/mstar-harness.js +100 -117
  2. package/package.json +1 -1
@@ -10916,11 +10916,6 @@ import fs3 from "node:fs";
10916
10916
  import os2 from "node:os";
10917
10917
  import path5 from "node:path";
10918
10918
 
10919
- // src/adapters/shared-install.ts
10920
- import fs2 from "node:fs";
10921
- import os from "node:os";
10922
- import path4 from "node:path";
10923
-
10924
10919
  // src/exec.ts
10925
10920
  import { execFileSync as execFileSync7 } from "node:child_process";
10926
10921
  function runCliCommand(command, opts = {}) {
@@ -10936,6 +10931,9 @@ function runCliCommand(command, opts = {}) {
10936
10931
  }
10937
10932
 
10938
10933
  // src/adapters/shared-install.ts
10934
+ import fs2 from "node:fs";
10935
+ import os from "node:os";
10936
+ import path4 from "node:path";
10939
10937
  var REPO_URL = "https://github.com/btspoony/mstar-harness.git";
10940
10938
  var PLUGIN_NAME = "morning-star-harness";
10941
10939
  var HARNESS_REPO_PATH = path4.join(os.homedir(), ".mstar", "harness");
@@ -11126,17 +11124,14 @@ function appendGitignore(projectRoot, entries, dryRun) {
11126
11124
  function appendHarnessProjectGitignore(projectRoot, dryRun) {
11127
11125
  return appendGitignore(projectRoot, HARNESS_PROCESS_GITIGNORE, dryRun);
11128
11126
  }
11129
- function homeRelativeSourcePath(targetPath) {
11130
- const rel = path4.relative(os.homedir(), targetPath).split(path4.sep).join("/");
11131
- return rel.startsWith("..") ? targetPath : `./${rel}`;
11132
- }
11133
11127
 
11134
11128
  // src/adapters/codex.ts
11135
- var MARKETPLACE_NAME = "personal";
11136
- var MARKETPLACE_DISPLAY_NAME = "Personal";
11137
- var GLOBAL_MARKETPLACE_PATH = path5.join(os2.homedir(), ".agents", "plugins", "marketplace.json");
11138
- var PLUGIN_CATEGORY = "Productivity";
11139
- var CODEX_PLUGIN_LINK = ".codex/plugins/mstar-harness";
11129
+ var CODEX_BIN = "codex";
11130
+ var CODEX_LOCAL_TIMEOUT_MS = 1e4;
11131
+ var CODEX_MARKETPLACE_TIMEOUT_MS = 300000;
11132
+ var MARKETPLACE_GIT_SOURCE = "btspoony/mstar-harness";
11133
+ var MARKETPLACE_NAME = "mstar-repo";
11134
+ var CODEX_INSTALL_HINT = "Install the Codex CLI (https://github.com/openai/codex), e.g. `npm install -g @openai/codex`, then re-run init.";
11140
11135
  var CODEX_AGENT_NAMES = [
11141
11136
  "product-manager",
11142
11137
  "architect",
@@ -11159,11 +11154,50 @@ var CODEX_PROJECT_COMMAND_NAMES = [
11159
11154
  "amazing-pr-review"
11160
11155
  ];
11161
11156
  var GLOBAL_ITERATION_SKILLS_WARNING = "Codex project-scoped commands (iteration-start / iteration-drive / iteration-loop / codebase-audit / amazing-pr-review) 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.";
11162
- function globalMarketplacePath() {
11163
- return GLOBAL_MARKETPLACE_PATH;
11157
+ function runCodex(args, dryRun, timeoutMs) {
11158
+ return runCliCommand([CODEX_BIN, ...args], { dryRun, timeoutMs, env: process.env });
11164
11159
  }
11165
- function projectMarketplacePath() {
11166
- return path5.join(resolveProjectRoot2(), ".agents", "plugins", "marketplace.json");
11160
+ function codexAvailable() {
11161
+ try {
11162
+ runCodex(["--version"], false, CODEX_LOCAL_TIMEOUT_MS);
11163
+ return true;
11164
+ } catch {
11165
+ return false;
11166
+ }
11167
+ }
11168
+ function configuredMarketplaceNames(dryRun) {
11169
+ if (dryRun)
11170
+ return [];
11171
+ const dump = runCodex(["plugin", "marketplace", "list", "--json"], false, CODEX_LOCAL_TIMEOUT_MS);
11172
+ const parsed = JSON.parse(dump);
11173
+ const list = Array.isArray(parsed.marketplaces) ? parsed.marketplaces : [];
11174
+ return list.map((entry) => entry && typeof entry.name === "string" ? entry.name : "").filter((name) => name !== "");
11175
+ }
11176
+ function installedPluginIds(dryRun) {
11177
+ if (dryRun)
11178
+ return [];
11179
+ const dump = runCodex(["plugin", "list", "--json"], false, CODEX_LOCAL_TIMEOUT_MS);
11180
+ const parsed = JSON.parse(dump);
11181
+ const list = Array.isArray(parsed.installed) ? parsed.installed : [];
11182
+ return list.map((entry) => entry && typeof entry.pluginId === "string" ? entry.pluginId : "").filter((pluginId) => pluginId !== "");
11183
+ }
11184
+ function legacyPersonalMarketplaceNote() {
11185
+ const legacyPath = path5.join(os2.homedir(), ".agents", "plugins", "marketplace.json");
11186
+ let raw;
11187
+ try {
11188
+ raw = fs3.readFileSync(legacyPath, "utf8");
11189
+ } catch {
11190
+ return null;
11191
+ }
11192
+ try {
11193
+ const parsed = JSON.parse(raw);
11194
+ const plugins = Array.isArray(parsed.plugins) ? parsed.plugins : [];
11195
+ const hasMstar = plugins.some((entry) => entry !== null && typeof entry === "object" && !Array.isArray(entry) && ("name" in entry) && entry.name === PLUGIN_NAME);
11196
+ if (hasMstar) {
11197
+ return `Legacy personal marketplace entry found at ${legacyPath} \u2014 the ${PLUGIN_NAME} plugin now installs from the repo marketplace (${MARKETPLACE_GIT_SOURCE}). Remove the entry, then install: codex plugin add ${PLUGIN_NAME}@${MARKETPLACE_NAME}`;
11198
+ }
11199
+ } catch {}
11200
+ return null;
11167
11201
  }
11168
11202
  function agentSourcePath(agentName) {
11169
11203
  return path5.join(HARNESS_REPO_PATH, "codex", "agents", `${agentName}.toml`);
@@ -11174,76 +11208,6 @@ function globalAgentLinkPath(agentName) {
11174
11208
  function projectAgentLinkPath(agentName) {
11175
11209
  return path5.join(resolveProjectRoot2(), ".codex", "agents", `${agentName}.toml`);
11176
11210
  }
11177
- function mstarEntry(scope) {
11178
- const sourcePath = scope === "global" ? homeRelativeSourcePath(HARNESS_REPO_PATH) : `./${CODEX_PLUGIN_LINK}`;
11179
- return {
11180
- name: PLUGIN_NAME,
11181
- source: {
11182
- source: "local",
11183
- path: sourcePath
11184
- },
11185
- policy: {
11186
- installation: "AVAILABLE",
11187
- authentication: "ON_INSTALL"
11188
- },
11189
- category: PLUGIN_CATEGORY
11190
- };
11191
- }
11192
- function normalizeMarketplace(raw) {
11193
- const next = ensureObject(raw);
11194
- next.name = MARKETPLACE_NAME;
11195
- const iface = ensureObject(next.interface);
11196
- if (typeof iface.displayName !== "string" || !iface.displayName.trim()) {
11197
- iface.displayName = MARKETPLACE_DISPLAY_NAME;
11198
- }
11199
- next.interface = iface;
11200
- if (!Array.isArray(next.plugins)) {
11201
- next.plugins = [];
11202
- }
11203
- return next;
11204
- }
11205
- function upsertEntry(raw, scope) {
11206
- const next = normalizeMarketplace(raw);
11207
- const plugins = next.plugins.filter((entry) => {
11208
- return !(entry && typeof entry === "object" && !Array.isArray(entry) && entry.name === PLUGIN_NAME);
11209
- });
11210
- plugins.push(mstarEntry(scope));
11211
- next.plugins = plugins;
11212
- return next;
11213
- }
11214
- function findEntry(raw) {
11215
- const plugins = Array.isArray(raw.plugins) ? raw.plugins : [];
11216
- return plugins.find((entry) => {
11217
- return entry && typeof entry === "object" && !Array.isArray(entry) && entry.name === PLUGIN_NAME;
11218
- });
11219
- }
11220
- function validateEntryShape(entry, scope, marketplacePath) {
11221
- const errors2 = [];
11222
- if (!entry) {
11223
- errors2.push(`Missing ${PLUGIN_NAME} entry in ${marketplacePath}.`);
11224
- return errors2;
11225
- }
11226
- const source = ensureObject(entry.source);
11227
- const expectedSourcePath = mstarEntry(scope).source.path;
11228
- if (source.source !== "local")
11229
- errors2.push("Codex marketplace entry source.source must be `local`.");
11230
- if (source.path !== expectedSourcePath) {
11231
- errors2.push(`Codex marketplace entry source.path must be ${expectedSourcePath}.`);
11232
- }
11233
- const policy = ensureObject(entry.policy);
11234
- if (policy.installation !== "AVAILABLE")
11235
- errors2.push("Codex marketplace entry policy.installation must be AVAILABLE.");
11236
- if (policy.authentication !== "ON_INSTALL")
11237
- errors2.push("Codex marketplace entry policy.authentication must be ON_INSTALL.");
11238
- if (entry.category !== PLUGIN_CATEGORY)
11239
- errors2.push(`Codex marketplace entry category must be ${PLUGIN_CATEGORY}.`);
11240
- return errors2;
11241
- }
11242
- function marketplacePath(scope) {
11243
- if (scope === "global")
11244
- return globalMarketplacePath();
11245
- return projectMarketplacePath();
11246
- }
11247
11211
  function ensureAgentLinks(scope, dryRun) {
11248
11212
  const notes = [];
11249
11213
  for (const agentName of CODEX_AGENT_NAMES) {
@@ -11301,59 +11265,78 @@ function validateIterationSkillLinks() {
11301
11265
  return errors2;
11302
11266
  }
11303
11267
  function runInit(scope, dryRun) {
11304
- const pathToMarketplace = marketplacePath(scope);
11305
- const current = readJson2(pathToMarketplace);
11306
- const next = upsertEntry(current, scope);
11307
- const existingEntry = findEntry(current);
11308
- const notes = ensureLocalHarnessRepo(dryRun);
11268
+ const notes = [];
11269
+ notes.push(...ensureLocalHarnessRepo(dryRun));
11270
+ const marketplaceArgs = ["plugin", "marketplace", "add", REPO_URL, "--ref", "main"];
11271
+ if (dryRun) {
11272
+ notes.push(`Would run: ${CODEX_BIN} ${marketplaceArgs.join(" ")}`);
11273
+ } else {
11274
+ if (!codexAvailable()) {
11275
+ throw new Error(`${CODEX_BIN} CLI not found on PATH. ${CODEX_INSTALL_HINT}`);
11276
+ }
11277
+ try {
11278
+ const already = configuredMarketplaceNames(false).includes(MARKETPLACE_NAME);
11279
+ if (already) {
11280
+ notes.push(`Marketplace ${MARKETPLACE_NAME} already configured.`);
11281
+ } else {
11282
+ runCodex(marketplaceArgs, false, CODEX_MARKETPLACE_TIMEOUT_MS);
11283
+ notes.push(`Added marketplace ${MARKETPLACE_NAME} from ${REPO_URL} (ref main).`);
11284
+ }
11285
+ } catch (error) {
11286
+ const message = error instanceof Error ? error.message : String(error);
11287
+ throw new Error(`Failed to add marketplace via ${CODEX_BIN}: ${message}`);
11288
+ }
11289
+ notes.push(`Next: codex plugin add ${PLUGIN_NAME}@${MARKETPLACE_NAME}`);
11290
+ }
11309
11291
  if (scope === "project") {
11310
11292
  const projectRoot = resolveProjectRoot2();
11311
- notes.push(ensureSymlink(HARNESS_REPO_PATH, path5.join(projectRoot, CODEX_PLUGIN_LINK), dryRun));
11312
- notes.push(...appendGitignore(projectRoot, [CODEX_PLUGIN_LINK, ".codex/agents/*.toml"], dryRun));
11293
+ notes.push(...appendGitignore(projectRoot, [".codex/agents/*.toml"], dryRun));
11313
11294
  notes.push(...appendHarnessProjectGitignore(projectRoot, dryRun));
11314
11295
  notes.push(...ensureIterationSkillLinks(dryRun));
11315
11296
  } else {
11316
11297
  notes.push(GLOBAL_ITERATION_SKILLS_WARNING);
11317
11298
  }
11318
11299
  notes.push(...ensureAgentLinks(scope, dryRun));
11319
- if (!dryRun)
11320
- writeJson2(pathToMarketplace, next);
11321
- notes.push(existingEntry ? `Updated ${PLUGIN_NAME} local marketplace entry.` : `Added ${PLUGIN_NAME} local marketplace entry.`);
11322
- notes.push(`Source path: ${mstarEntry(scope).source.path}`);
11323
- notes.push(`Install after init: codex plugin add ${PLUGIN_NAME} --marketplace ${MARKETPLACE_NAME}`);
11324
11300
  return {
11325
- location: pathToMarketplace,
11301
+ location: `${CODEX_BIN} marketplaces (config.toml)`,
11326
11302
  notes
11327
11303
  };
11328
11304
  }
11329
11305
  function runDoctor(scope) {
11330
- const pathToMarketplace = marketplacePath(scope);
11331
11306
  const errors2 = validateLocalHarnessRepo();
11332
- if (!fs3.existsSync(pathToMarketplace)) {
11333
- return { location: pathToMarketplace, errors: [...errors2, `Missing Codex marketplace: ${pathToMarketplace}`] };
11307
+ const notes = [];
11308
+ const legacyNote = legacyPersonalMarketplaceNote();
11309
+ if (legacyNote)
11310
+ notes.push(legacyNote);
11311
+ if (!codexAvailable()) {
11312
+ errors2.push(`${CODEX_BIN} CLI not found on PATH. ${CODEX_INSTALL_HINT}`);
11313
+ return { location: `${CODEX_BIN} marketplaces (config.toml)`, errors: errors2, notes };
11334
11314
  }
11335
- const marketplace = readJson2(pathToMarketplace);
11336
- if (marketplace.name !== MARKETPLACE_NAME) {
11337
- errors2.push(`Codex personal marketplace name must be ${MARKETPLACE_NAME}.`);
11315
+ try {
11316
+ const marketplaces = configuredMarketplaceNames(false);
11317
+ if (!marketplaces.includes(MARKETPLACE_NAME)) {
11318
+ errors2.push(`Marketplace ${MARKETPLACE_NAME} not configured (run init, or: ${CODEX_BIN} plugin marketplace add ${REPO_URL} --ref main).`);
11319
+ }
11320
+ const installed = installedPluginIds(false);
11321
+ const pluginId = `${PLUGIN_NAME}@${MARKETPLACE_NAME}`;
11322
+ if (marketplaces.includes(MARKETPLACE_NAME) && !installed.includes(pluginId)) {
11323
+ notes.push(`Plugin not installed yet: ${CODEX_BIN} plugin add ${pluginId}`);
11324
+ }
11325
+ } catch (error) {
11326
+ const message = error instanceof Error ? error.message : String(error);
11327
+ errors2.push(`Could not query ${CODEX_BIN} plugin marketplace list: ${message}`);
11338
11328
  }
11339
- errors2.push(...validateEntryShape(findEntry(marketplace), scope, pathToMarketplace));
11340
11329
  if (scope === "project") {
11341
11330
  const projectRoot = resolveProjectRoot2();
11342
- errors2.push(...validateSymlink(HARNESS_REPO_PATH, path5.join(projectRoot, CODEX_PLUGIN_LINK)));
11343
11331
  const gitignorePath = path5.join(projectRoot, ".gitignore");
11344
11332
  const gitignore = fs3.existsSync(gitignorePath) ? fs3.readFileSync(gitignorePath, "utf8") : "";
11345
- const lines = gitignore.split(/\r?\n/);
11346
- if (!lines.includes(CODEX_PLUGIN_LINK))
11347
- errors2.push(`Missing .gitignore entry: ${CODEX_PLUGIN_LINK}`);
11348
- if (!lines.includes(".codex/agents/*.toml"))
11349
- errors2.push("Missing .gitignore entry: .codex/agents/*.toml");
11350
11333
  for (const entry of missingHarnessProcessGitignoreEntries(gitignore)) {
11351
11334
  errors2.push(`Missing .gitignore entry: ${entry}`);
11352
11335
  }
11353
11336
  errors2.push(...validateIterationSkillLinks());
11354
11337
  }
11355
11338
  errors2.push(...validateAgentLinks(scope));
11356
- return { location: pathToMarketplace, errors: errors2 };
11339
+ return { location: `${CODEX_BIN} marketplaces (config.toml)`, errors: errors2, notes };
11357
11340
  }
11358
11341
  var codexAdapter = {
11359
11342
  target: "codex",
@@ -11921,7 +11904,7 @@ var MARKETPLACE_ID = "mstar-local";
11921
11904
  var MARKETPLACE_NAME2 = "mstar-local";
11922
11905
  var MARKETPLACE_DESCRIPTION = "Morning Star harness marketplace (GitHub source).";
11923
11906
  var PLUGIN_DESCRIPTION = "Multi-agent code harness framework with unified skills for OpenCode, Cursor, Codex, Kimi Code, and ZCode.";
11924
- var PLUGIN_CATEGORY2 = "Productivity";
11907
+ var PLUGIN_CATEGORY = "Productivity";
11925
11908
  var GITHUB_REPO = "btspoony/mstar-harness";
11926
11909
  var GITHUB_REF = "main";
11927
11910
  var ZCODE_PLUGIN_MARKER = ".zcode-plugin/plugin.json";
@@ -11941,7 +11924,7 @@ function marketplacePluginEntry() {
11941
11924
  source: { ...GITHUB_SOURCE },
11942
11925
  description: PLUGIN_DESCRIPTION,
11943
11926
  version: readHarnessVersion(),
11944
- category: PLUGIN_CATEGORY2
11927
+ category: PLUGIN_CATEGORY
11945
11928
  };
11946
11929
  }
11947
11930
  function knownMarketplaceEntry(existing) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mstar-harness/cli",
3
- "version": "3.6.0-alpha.2",
3
+ "version": "3.6.0-alpha.3",
4
4
  "description": "Morning Star harness CLI — installer bootstrap + mstar workflow verbs (path/status/lease/sdd/iteration/dispatch/worktree/lint/design-md/audit/compound/host/skill).",
5
5
  "license": "MIT",
6
6
  "repository": {