@massa-ai/codex-plugin 1.25.0 → 1.26.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.
Files changed (89) hide show
  1. package/.codex-plugin/plugin.json +1 -1
  2. package/agent-profiles/balanced/massa-ai-architecture-specialist.toml +62 -0
  3. package/agent-profiles/balanced/massa-ai-audit-specialist.toml +78 -0
  4. package/agent-profiles/balanced/massa-ai-builder.toml +64 -0
  5. package/agent-profiles/balanced/massa-ai-context-curator.toml +64 -0
  6. package/agent-profiles/balanced/massa-ai-documentation-agent.toml +62 -0
  7. package/agent-profiles/balanced/massa-ai-furps-analyst.toml +68 -0
  8. package/agent-profiles/balanced/massa-ai-investigator.toml +65 -0
  9. package/agent-profiles/balanced/massa-ai-judge.toml +99 -0
  10. package/agent-profiles/balanced/massa-ai-meta-judge.toml +86 -0
  11. package/agent-profiles/balanced/massa-ai-mobile-specialist.toml +79 -0
  12. package/agent-profiles/balanced/massa-ai-navigator.toml +72 -0
  13. package/agent-profiles/balanced/massa-ai-plan-critic.toml +87 -0
  14. package/agent-profiles/balanced/massa-ai-planner.toml +62 -0
  15. package/agent-profiles/balanced/massa-ai-requirements-analyst.toml +61 -0
  16. package/agent-profiles/balanced/massa-ai-reviewer.toml +63 -0
  17. package/agent-profiles/balanced/massa-ai-test-engineer.toml +63 -0
  18. package/agent-profiles/balanced/massa-ai-verification-agent.toml +62 -0
  19. package/agent-profiles/cheap/massa-ai-architecture-specialist.toml +62 -0
  20. package/agent-profiles/cheap/massa-ai-audit-specialist.toml +78 -0
  21. package/agent-profiles/cheap/massa-ai-builder.toml +64 -0
  22. package/agent-profiles/cheap/massa-ai-context-curator.toml +64 -0
  23. package/agent-profiles/cheap/massa-ai-documentation-agent.toml +62 -0
  24. package/agent-profiles/cheap/massa-ai-furps-analyst.toml +68 -0
  25. package/agent-profiles/cheap/massa-ai-investigator.toml +65 -0
  26. package/agent-profiles/cheap/massa-ai-judge.toml +99 -0
  27. package/agent-profiles/cheap/massa-ai-meta-judge.toml +86 -0
  28. package/agent-profiles/cheap/massa-ai-mobile-specialist.toml +79 -0
  29. package/agent-profiles/cheap/massa-ai-navigator.toml +72 -0
  30. package/agent-profiles/cheap/massa-ai-plan-critic.toml +87 -0
  31. package/agent-profiles/cheap/massa-ai-planner.toml +62 -0
  32. package/agent-profiles/cheap/massa-ai-requirements-analyst.toml +61 -0
  33. package/agent-profiles/cheap/massa-ai-reviewer.toml +63 -0
  34. package/agent-profiles/cheap/massa-ai-test-engineer.toml +63 -0
  35. package/agent-profiles/cheap/massa-ai-verification-agent.toml +62 -0
  36. package/agent-profiles/heavy/massa-ai-architecture-specialist.toml +62 -0
  37. package/agent-profiles/heavy/massa-ai-audit-specialist.toml +78 -0
  38. package/agent-profiles/heavy/massa-ai-builder.toml +64 -0
  39. package/agent-profiles/heavy/massa-ai-context-curator.toml +64 -0
  40. package/agent-profiles/heavy/massa-ai-documentation-agent.toml +62 -0
  41. package/agent-profiles/heavy/massa-ai-furps-analyst.toml +68 -0
  42. package/agent-profiles/heavy/massa-ai-investigator.toml +65 -0
  43. package/agent-profiles/heavy/massa-ai-judge.toml +99 -0
  44. package/agent-profiles/heavy/massa-ai-meta-judge.toml +86 -0
  45. package/agent-profiles/heavy/massa-ai-mobile-specialist.toml +79 -0
  46. package/agent-profiles/heavy/massa-ai-navigator.toml +72 -0
  47. package/agent-profiles/heavy/massa-ai-plan-critic.toml +87 -0
  48. package/agent-profiles/heavy/massa-ai-planner.toml +62 -0
  49. package/agent-profiles/heavy/massa-ai-requirements-analyst.toml +61 -0
  50. package/agent-profiles/heavy/massa-ai-reviewer.toml +63 -0
  51. package/agent-profiles/heavy/massa-ai-test-engineer.toml +63 -0
  52. package/agent-profiles/heavy/massa-ai-verification-agent.toml +62 -0
  53. package/agent-profiles/home/massa-ai-architecture-specialist.toml +62 -0
  54. package/agent-profiles/home/massa-ai-audit-specialist.toml +78 -0
  55. package/agent-profiles/home/massa-ai-builder.toml +64 -0
  56. package/agent-profiles/home/massa-ai-context-curator.toml +64 -0
  57. package/agent-profiles/home/massa-ai-documentation-agent.toml +62 -0
  58. package/agent-profiles/home/massa-ai-furps-analyst.toml +68 -0
  59. package/agent-profiles/home/massa-ai-investigator.toml +65 -0
  60. package/agent-profiles/home/massa-ai-judge.toml +99 -0
  61. package/agent-profiles/home/massa-ai-meta-judge.toml +86 -0
  62. package/agent-profiles/home/massa-ai-mobile-specialist.toml +79 -0
  63. package/agent-profiles/home/massa-ai-navigator.toml +72 -0
  64. package/agent-profiles/home/massa-ai-plan-critic.toml +87 -0
  65. package/agent-profiles/home/massa-ai-planner.toml +62 -0
  66. package/agent-profiles/home/massa-ai-requirements-analyst.toml +61 -0
  67. package/agent-profiles/home/massa-ai-reviewer.toml +63 -0
  68. package/agent-profiles/home/massa-ai-test-engineer.toml +63 -0
  69. package/agent-profiles/home/massa-ai-verification-agent.toml +62 -0
  70. package/agent-profiles/work/massa-ai-architecture-specialist.toml +62 -0
  71. package/agent-profiles/work/massa-ai-audit-specialist.toml +78 -0
  72. package/agent-profiles/work/massa-ai-builder.toml +64 -0
  73. package/agent-profiles/work/massa-ai-context-curator.toml +64 -0
  74. package/agent-profiles/work/massa-ai-documentation-agent.toml +62 -0
  75. package/agent-profiles/work/massa-ai-furps-analyst.toml +68 -0
  76. package/agent-profiles/work/massa-ai-investigator.toml +65 -0
  77. package/agent-profiles/work/massa-ai-judge.toml +99 -0
  78. package/agent-profiles/work/massa-ai-meta-judge.toml +86 -0
  79. package/agent-profiles/work/massa-ai-mobile-specialist.toml +79 -0
  80. package/agent-profiles/work/massa-ai-navigator.toml +72 -0
  81. package/agent-profiles/work/massa-ai-plan-critic.toml +87 -0
  82. package/agent-profiles/work/massa-ai-planner.toml +62 -0
  83. package/agent-profiles/work/massa-ai-requirements-analyst.toml +61 -0
  84. package/agent-profiles/work/massa-ai-reviewer.toml +63 -0
  85. package/agent-profiles/work/massa-ai-test-engineer.toml +63 -0
  86. package/agent-profiles/work/massa-ai-verification-agent.toml +62 -0
  87. package/install.sh +103 -8
  88. package/package.json +2 -1
  89. package/skills/profile/SKILL.md +39 -0
package/install.sh CHANGED
@@ -78,6 +78,12 @@ PLUGIN_DIR="$CODEX_DIR/plugins/massa-ai"
78
78
  HOOKS_JSON="$CODEX_DIR/hooks.json"
79
79
  AGENTS_DIR="$CODEX_DIR/agents"
80
80
 
81
+ # Model-profile variant tree (T8, design Component 3 / MPS-04). Source is the
82
+ # bundle's per-profile agent-profiles/<p>/ (sibling of agents/, A5); dest is
83
+ # the engine's own host path table: $CODEX_DIR/massa-ai/agent-profiles/<p>/.
84
+ VARIANTS_SRC="$SCRIPT_DIR/agent-profiles"
85
+ VARIANTS_DEST="$CODEX_DIR/massa-ai/agent-profiles"
86
+
81
87
  # Array-append merge (F5 mitigation): for each of the 6 events, append the
82
88
  # massa-ai hook entry to the event's array if no entry with
83
89
  # _massaAiOwned: true already exists. Backup before first write. Uses node
@@ -299,10 +305,22 @@ if (typeof data.platforms !== "object" || data.platforms === null || Array.isArr
299
305
  data.version = 2;
300
306
  const prev = data.platforms[host];
301
307
  data.platforms[host] = { root, skillsOwner: "plugin", skills: ["massa-ai", "persona-router"] };
302
- // The whole-record replace must not drop the plugin version record a previous
303
- // successful install wrote (R2) — re-attach it.
304
- if (prev && typeof prev === "object" && !Array.isArray(prev) && prev.plugin && typeof prev.plugin === "object") {
305
- data.platforms[host].plugin = prev.plugin;
308
+ // The whole-record replace must not drop fields a previous successful install
309
+ // wrote (R2) — re-attach them. modelProfile (T10, MPS-03 round-trip
310
+ // obligation) is engine-owned; installRoute is installer-owned but written by
311
+ // a LATER step of this same install (record_plugin_version) — both must
312
+ // survive this earlier whole-record replace or a switched profile / recorded
313
+ // route silently vanishes on the next skills-bundling pass.
314
+ if (prev && typeof prev === "object" && !Array.isArray(prev)) {
315
+ if (prev.plugin && typeof prev.plugin === "object") {
316
+ data.platforms[host].plugin = prev.plugin;
317
+ }
318
+ if (prev.modelProfile && typeof prev.modelProfile === "object") {
319
+ data.platforms[host].modelProfile = prev.modelProfile;
320
+ }
321
+ if (typeof prev.installRoute === "string") {
322
+ data.platforms[host].installRoute = prev.installRoute;
323
+ }
306
324
  }
307
325
  fs.mkdirSync(path.dirname(file), { recursive: true });
308
326
  fs.writeFileSync(file, JSON.stringify(data, null, 2) + "\n");
@@ -376,18 +394,27 @@ record_plugin_version() {
376
394
  return 0
377
395
  fi
378
396
 
379
- local version installed_at
397
+ local version installed_at route
380
398
  version="$(sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$SCRIPT_DIR/package.json" | head -n 1)"
381
399
  installed_at="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
400
+ # installRoute (T8, design F1): installer-owned, engine-read-only. Unlike
401
+ # Claude, Codex's plugin/marketplace registration (register_codex_plugin) is
402
+ # ADDITIVE — it only affects /plugins visibility. The agent TOML files
403
+ # always land in $AGENTS_DIR regardless of whether that registration
404
+ # succeeds (see the unconditional copy loop below), so Codex has no
405
+ # "read in place, no local files" mode the way Claude's marketplace route
406
+ # does — installRoute is unconditionally "file" here, reflecting the one
407
+ # install shape Codex agents ever take. Written on EVERY install path.
408
+ route="file"
382
409
 
383
410
  # Tolerant of a corrupt/missing state file (rewrites a minimal valid one —
384
411
  # AC-8). A record-write failure warns but never fails the install: the next
385
412
  # run treats the host as unknown-version and reinstalls.
386
- "$runner" - "$HARNESS_STATE_FILE" "$HARNESS_HOST" "$CODEX_DIR" "$version" "$installed_at" <<'NODE' || \
413
+ "$runner" - "$HARNESS_STATE_FILE" "$HARNESS_HOST" "$CODEX_DIR" "$version" "$installed_at" "$route" <<'NODE' || \
387
414
  echo " ⚠ could not record the plugin version — next run will reinstall (unknown version)" >&2
388
415
  const fs = require("fs");
389
416
  const path = require("path");
390
- const [, , file, host, root, version, installedAt] = process.argv;
417
+ const [, , file, host, root, version, installedAt, installRoute] = process.argv;
391
418
  let data = { version: 2, platforms: {} };
392
419
  try {
393
420
  const existing = JSON.parse(fs.readFileSync(file, "utf8"));
@@ -404,12 +431,54 @@ const rec =
404
431
  ? data.platforms[host]
405
432
  : { root, skillsOwner: "plugin", skills: [] };
406
433
  rec.plugin = { version, installedAt };
434
+ // installRoute is installer-owned (like plugin above); modelProfile is NEVER
435
+ // written here — the switch engine (packages/shared/src/profile-switch/) is
436
+ // its sole writer, and this installer only ever reads it (see
437
+ // apply_recorded_profile below).
438
+ rec.installRoute = installRoute;
407
439
  data.platforms[host] = rec;
408
440
  fs.mkdirSync(path.dirname(file), { recursive: true });
409
441
  fs.writeFileSync(file, JSON.stringify(data, null, 2) + "\n");
410
442
  NODE
411
443
  }
412
444
 
445
+ # ── Model-profile variant tree + recorded-profile re-apply (T8, MPS-04) ─────
446
+ # Read-side only: this installer never writes platforms[host].modelProfile —
447
+ # see the comment above record_plugin_version's NODE block. It only (a)
448
+ # refreshes the on-disk variant tree so an offline switch has files to copy
449
+ # from, and (b) re-applies a previously recorded profile's active agent set on
450
+ # install/upgrade, so a plugin upgrade never silently reverts a switched
451
+ # profile back to the shipped default.
452
+ install_variant_tree() {
453
+ [[ -d "$VARIANTS_SRC" ]] || return 0
454
+ rm -rf "$VARIANTS_DEST"
455
+ mkdir -p "$VARIANTS_DEST"
456
+ cp -R "$VARIANTS_SRC/." "$VARIANTS_DEST/"
457
+ vecho " + model-profile variant tree refreshed at $VARIANTS_DEST"
458
+ }
459
+
460
+ # Prints the recorded profile name (platforms[codex].modelProfile.profile), or
461
+ # an empty string when unset/unreadable. Never throws — a corrupt or missing
462
+ # state file just means "no recorded profile", not an install failure.
463
+ recorded_profile() {
464
+ local runner="$1"
465
+ "$runner" - "$HARNESS_STATE_FILE" "$HARNESS_HOST" <<'NODE'
466
+ const fs = require("fs");
467
+ const [, , file, host] = process.argv;
468
+ try {
469
+ const data = JSON.parse(fs.readFileSync(file, "utf8"));
470
+ const rec = data && data.platforms && data.platforms[host];
471
+ const profile =
472
+ rec && rec.modelProfile && typeof rec.modelProfile.profile === "string"
473
+ ? rec.modelProfile.profile
474
+ : "";
475
+ process.stdout.write(profile);
476
+ } catch {
477
+ process.stdout.write("");
478
+ }
479
+ NODE
480
+ }
481
+
413
482
  # ── Plugin-registry registration (delegated to the codex CLI) ───────────────
414
483
  # The CLI owns config.toml's [marketplaces.*] / [plugins."x@y"] tables and the
415
484
  # plugins/cache layout, so it is the only supported way to reach /plugins.
@@ -551,9 +620,33 @@ vecho " + 6 massa-ai hook events wired (array-append, user hooks preserved)"
551
620
  # plugin dir — Codex custom agents load from the config-root agents/ dir, not
552
621
  # the plugin dir). Each file carries a "# massa-ai-owned" top comment for
553
622
  # scoped uninstall (R3: shared agents dir, user agents preserved).
623
+ #
624
+ # Model-profile re-apply (T8, MPS-04): if a switch previously recorded a
625
+ # profile for this host, and the bundle ships that profile's variant, the
626
+ # ACTIVE set comes from agent-profiles/<profile>/ instead of the shipped
627
+ # default — an upgrade must never silently revert a switched profile.
628
+ # Recorded-but-missing-from-bundle is a loud fallback to the default, never a
629
+ # silent one.
554
630
  mkdir -p "$AGENTS_DIR"
631
+ ACTIVE_AGENTS_SRC="$SCRIPT_DIR/agents"
632
+ json_runner=""
633
+ if command -v node &>/dev/null; then json_runner="node"
634
+ elif command -v bun &>/dev/null; then json_runner="bun"
635
+ fi
636
+ if [[ -n "$json_runner" ]]; then
637
+ RECORDED_PROFILE="$(recorded_profile "$json_runner")"
638
+ if [[ -n "$RECORDED_PROFILE" ]]; then
639
+ if [[ -d "$VARIANTS_SRC/$RECORDED_PROFILE" ]]; then
640
+ ACTIVE_AGENTS_SRC="$VARIANTS_SRC/$RECORDED_PROFILE"
641
+ echo " ↷ re-applying recorded model profile '$RECORDED_PROFILE'"
642
+ else
643
+ echo " ⚠ recorded model profile '$RECORDED_PROFILE' is not in this bundle — falling back to the default profile" >&2
644
+ fi
645
+ fi
646
+ fi
647
+
555
648
  specialist_count=0
556
- for src in "$SCRIPT_DIR/agents/"massa-ai-*.toml; do
649
+ for src in "$ACTIVE_AGENTS_SRC/"massa-ai-*.toml; do
557
650
  [[ -f "$src" ]] || continue
558
651
  name="$(basename "$src")"
559
652
  cp "$src" "$AGENTS_DIR/$name"
@@ -562,6 +655,8 @@ for src in "$SCRIPT_DIR/agents/"massa-ai-*.toml; do
562
655
  done
563
656
  vecho " + ${specialist_count} subagent specialists (generated from skills/agents/*/SKILL.md)"
564
657
 
658
+ install_variant_tree
659
+
565
660
  # Skills bundling (PDO-08, 09): install massa-ai/persona-router into the
566
661
  # shared harness skills directory, unless scripts/install-skills.sh already
567
662
  # owns it for this platform.
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "@massa-ai/codex-plugin",
3
- "version": "1.25.0",
3
+ "version": "1.26.0",
4
4
  "description": "massa-ai plugin for Codex — semantic code search, memory, and context compression",
5
5
  "files": [
6
6
  "agents",
7
+ "agent-profiles",
7
8
  "hooks",
8
9
  "skills",
9
10
  "install.sh",
@@ -0,0 +1,39 @@
1
+ ---
2
+ name: profile
3
+ description: Switch the installed massa-ai agents to a registry model profile (e.g. "work", "cheap", "home") or report the currently active profile per host. Use when the user asks to change/switch the model profile, asks which models the agents currently use, or asks to preview a profile switch. Do NOT use for editing the model registry itself (a registry edit is a massa-ai repository change, not a runtime switch) and do NOT claim the new profile is active before the user restarts the host session.
4
+ license: MIT
5
+ metadata:
6
+ author: Luiz Massa
7
+ version: 1.0.0
8
+ ---
9
+
10
+ # Profile Switch Skill
11
+
12
+ ## Mission
13
+ Drive the one massa-ai model-profile switch engine and relay its report — never a second implementation.
14
+
15
+ ## When To Use
16
+ - The user asks to switch, change, or set the model profile (by name, e.g. "work", "cheap", "home", "balanced").
17
+ - The user asks what profile is currently active, or which profiles are shipped.
18
+ - The user asks to preview a switch without applying it.
19
+
20
+ ## How To Drive It
21
+ There is exactly one switch implementation (`@massa-ai/shared`'s switch engine); every front — this skill, the MCP tools, and both `massa-ai-config` CLIs — calls the same engine and returns the same per-host report shape. Prefer whichever front is already available in the session:
22
+
23
+ - **MCP tools** (preferred when the massa-ai MCP server is connected): call `profile_list` to report shipped profiles + per-host active profile + bundle version, and `profile_set` to switch (`{profile, host?, dryRun?}`).
24
+ - **CLI fallback**: `massa-ai-config profile list` / `massa-ai-config profile show` / `massa-ai-config profile set <name> [--host <h>] [--dry-run]`.
25
+
26
+ Default to a dry run first when the user has not explicitly asked to apply the switch immediately — `dryRun: true` (MCP) or `--dry-run` (CLI) previews the per-host plan and changes nothing.
27
+
28
+ ## Relaying The Result
29
+ Always relay the per-host outcome and the restart notice verbatim in substance, not just "done":
30
+
31
+ - Report each host as switched / skipped (with its reason) / unsupported (with its reason) / failed (with its reason). Cursor is always reported skipped — every tier resolves to inherit, so switching it is a no-op by design, not an error.
32
+ - When at least one host switched (non-dry-run), state explicitly that a session restart of that host is required before the new models take effect — hosts load agent definitions at session start; there is no live in-session switch.
33
+ - On a dry run, say so and that no files changed.
34
+ - On a fully failed request (e.g. unknown profile name), relay the named error and the list of profiles the report says are actually available — never guess a profile name.
35
+
36
+ ## Restrictions
37
+ - Never invent a profile name; only use names the engine's own report lists as shipped/available.
38
+ - Never claim a profile switch is "live" before the affected host's session restarts.
39
+ - Never edit the model-profile registry (`skills/model-profiles.json`) to satisfy a switch request — that is a build-time registry change owned by a different workflow, not a runtime switch.