@mutmutco/codex-plugin 4.5.207 → 4.5.209

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mmi",
3
- "version": "4.5.207",
3
+ "version": "4.5.209",
4
4
  "mmiCompat": "4.x",
5
5
  "description": "MMI workflow skills and org gates delivery.",
6
6
  "author": {
package/cli/dist/main.cjs CHANGED
@@ -1598,13 +1598,15 @@ __export(index_exports, {
1598
1598
  commandOwnLongFlags: () => commandOwnLongFlags,
1599
1599
  envHealLockPath: () => envHealLockPath,
1600
1600
  isOrgRegisteredRepo: () => isOrgRegisteredRepo,
1601
+ normalizeBoardClaimIssueArgv: () => normalizeBoardClaimIssueArgv,
1601
1602
  parseInvalidChoiceError: () => parseInvalidChoiceError,
1602
1603
  positionalTargetForm: () => positionalTargetForm,
1603
1604
  registryClientDeps: () => registryClientDeps,
1604
1605
  repoSlug: () => repoSlug,
1605
1606
  suggestCommandPath: () => suggestCommandPath,
1606
1607
  unknownCommandCandidates: () => unknownCommandCandidates,
1607
- unknownCommandTail: () => unknownCommandTail
1608
+ unknownCommandTail: () => unknownCommandTail,
1609
+ workboardClaimRecovery: () => workboardClaimRecovery
1608
1610
  });
1609
1611
  module.exports = __toCommonJS(index_exports);
1610
1612
 
@@ -6350,6 +6352,81 @@ function boardClaimStatusFlagRecovery(flag, canonicalPath, argv) {
6350
6352
  corrected: `mmi-cli ${kept.join(" ")}`
6351
6353
  };
6352
6354
  }
6355
+ var BOARD_CLAIM_OWN_FLAGS = ["--repo", "--for", "--force", "--check", "--allow-partial", "--json"];
6356
+ function splitInlineSelectors(argv, flags) {
6357
+ const out = [];
6358
+ for (const tok of argv) {
6359
+ const eq = tok.indexOf("=");
6360
+ if (tok.startsWith("--") && eq > 0 && flags.includes(tok.slice(0, eq))) {
6361
+ out.push(tok.slice(0, eq), tok.slice(eq + 1));
6362
+ } else {
6363
+ out.push(tok);
6364
+ }
6365
+ }
6366
+ return out;
6367
+ }
6368
+ function workboardClaimRecovery(unknownToken, argv, paths, ownFlags = BOARD_CLAIM_OWN_FLAGS) {
6369
+ if (unknownToken !== "workboard") return void 0;
6370
+ const catalog = [...paths];
6371
+ if (!catalog.includes("oracle board claim") && !catalog.includes("board claim")) return void 0;
6372
+ const tail = unknownCommandTail(argv, "workboard");
6373
+ if (tail[0] !== "claim") return void 0;
6374
+ const canonicalPath = "oracle board claim";
6375
+ const positionals = tail.slice(1);
6376
+ let corrected;
6377
+ if (positionals.length > 0) {
6378
+ corrected = [`mmi-cli ${canonicalPath}`, ...positionals, ...survivingFlagArgs(argv, "", ownFlags)].join(" ");
6379
+ } else {
6380
+ const normalized = splitInlineSelectors(argv, ["--issue", "--number"]);
6381
+ const usedFlag = normalized.includes("--issue") ? "--issue" : normalized.includes("--number") ? "--number" : "--issue";
6382
+ corrected = formatPositionalTarget(canonicalPath, "issues", { flag: usedFlag, argv: normalized, ownFlags });
6383
+ }
6384
+ return { canonicalPath, corrected, hint: `did you mean \`${corrected}\`?` };
6385
+ }
6386
+ var BOARD_CLAIM_VALUE_FLAGS = /* @__PURE__ */ new Set(["--repo", "--for", "--status"]);
6387
+ var BOARD_CLAIM_BOOLEAN_FLAGS = /* @__PURE__ */ new Set(["--json", "--force", "--check", "--allow-partial", "--help", "-h"]);
6388
+ function normalizeBoardClaimIssueArgv(argv) {
6389
+ let claimAt;
6390
+ if (argv[2] === "board" && argv[3] === "claim") claimAt = 3;
6391
+ else if (argv[2] === "oracle" && argv[3] === "board" && argv[4] === "claim") claimAt = 4;
6392
+ else return false;
6393
+ let issueAt = -1;
6394
+ let issueSpan = 0;
6395
+ let value;
6396
+ for (let i = claimAt + 1; i < argv.length; i += 1) {
6397
+ const tok = argv[i];
6398
+ if (tok === "--issue" || tok.startsWith("--issue=")) {
6399
+ if (issueAt >= 0) return false;
6400
+ issueAt = i;
6401
+ if (tok === "--issue") {
6402
+ const next = argv[i + 1];
6403
+ if (next === void 0 || next === "" || next.startsWith("-")) return false;
6404
+ value = next;
6405
+ issueSpan = 2;
6406
+ i += 1;
6407
+ } else {
6408
+ value = tok.slice("--issue=".length);
6409
+ if (value === "" || value.startsWith("-")) return false;
6410
+ issueSpan = 1;
6411
+ }
6412
+ continue;
6413
+ }
6414
+ if (tok.startsWith("-")) {
6415
+ const name = tok.includes("=") ? tok.slice(0, tok.indexOf("=")) : tok;
6416
+ if (BOARD_CLAIM_VALUE_FLAGS.has(name)) {
6417
+ if (!tok.includes("=") && argv[i + 1] !== void 0 && !argv[i + 1].startsWith("-")) i += 1;
6418
+ continue;
6419
+ }
6420
+ if (BOARD_CLAIM_BOOLEAN_FLAGS.has(tok)) continue;
6421
+ return false;
6422
+ }
6423
+ return false;
6424
+ }
6425
+ if (issueAt < 0 || value === void 0) return false;
6426
+ argv.splice(issueAt, issueSpan);
6427
+ argv.splice(claimAt + 1, 0, value);
6428
+ return true;
6429
+ }
6353
6430
  function classifyParseError(plain) {
6354
6431
  if (/unknown command/i.test(plain)) return "unknown-command";
6355
6432
  if (/unknown option|missing required argument|too many arguments|argument missing|is invalid\. Allowed choices are|cannot be used with/i.test(plain)) {
@@ -15498,12 +15575,13 @@ function laneContestParts(contest) {
15498
15575
  function isUnknownHold(contest) {
15499
15576
  return !contest.marker && contest.live.length === 0 && contest.unverifiable.length > 0;
15500
15577
  }
15578
+ var CONTESTED_CLAIM_RECOVERY = "leave the holder's work untouched and choose another unclaimed item or coordinate a handoff (use --force only for an intentional takeover)";
15501
15579
  function laneContestMessage(ref, contest, verb) {
15502
15580
  const { holder, why } = laneContestParts(contest);
15503
15581
  if (isUnknownHold(contest)) {
15504
- return verb === "claim" ? `${ref} cannot be verified as free: ${holder} (${why}); the liveness reads failed so the claim is refused fail-closed \u2014 re-run with --force to take it anyway` : `refusing to unclaim ${ref}: ${holder} (${why}); the liveness reads failed so the unclaim is refused fail-closed \u2014 re-run with --force --holder-dead once you have evidence the holder lane is dead, or wait for it to go stale (#6625)`;
15582
+ return verb === "claim" ? `${ref} cannot be verified as free: ${holder} (${why}); the liveness reads failed so the claim is refused fail-closed \u2014 ${CONTESTED_CLAIM_RECOVERY}` : `refusing to unclaim ${ref}: ${holder} (${why}); the liveness reads failed so the unclaim is refused fail-closed \u2014 re-run with --force --holder-dead once you have evidence the holder lane is dead, or wait for it to go stale (#6625)`;
15505
15583
  }
15506
- return verb === "claim" ? `${ref} is already claimed by ${holder} with live evidence of active work (${why}); re-run with --force to take it anyway` : `refusing to unclaim ${ref}: ${holder} shows live evidence of active work (${why}); re-run with --force --holder-dead once you have evidence the holder lane is dead, or wait for it to go stale (#6625)`;
15584
+ return verb === "claim" ? `${ref} is already claimed by ${holder} with live evidence of active work (${why}); ${CONTESTED_CLAIM_RECOVERY}` : `refusing to unclaim ${ref}: ${holder} shows live evidence of active work (${why}); re-run with --force --holder-dead once you have evidence the holder lane is dead, or wait for it to go stale (#6625)`;
15507
15585
  }
15508
15586
  function ghError(e) {
15509
15587
  const err = e;
@@ -19343,10 +19421,10 @@ var rollout_plan_default = {
19343
19421
  note: "The v4.0.0 stamp happens at cut time (D6e #4463); until then the candidate is the origin/development head artifacts (built cli/dist + npm pack), identity proven by dist content hash (D6a)."
19344
19422
  },
19345
19423
  baseline: {
19346
- version: "4.5.207",
19347
- tag: "v4.5.207",
19348
- commit: "55e3ac7b8df0",
19349
- npm: "@mutmutco/cli@4.5.207"
19424
+ version: "4.5.209",
19425
+ tag: "v4.5.209",
19426
+ commit: "2449709d554c",
19427
+ npm: "@mutmutco/cli@4.5.209"
19350
19428
  },
19351
19429
  exitCriterion: "fleet-n-of-n",
19352
19430
  hubOnlyShortcut: "forbidden",
@@ -19363,14 +19441,14 @@ var rollout_plan_default = {
19363
19441
  repo: "mutmutco/mmi-hub",
19364
19442
  role: "canary",
19365
19443
  schedule: "train",
19366
- v3Target: "v4.5.207"
19444
+ v3Target: "v4.5.209"
19367
19445
  }
19368
19446
  ],
19369
19447
  rollbackTrigger: "Any red inside the post-contract soak window: `devops train gate` FAIL attributable to the v4 doors, Hub endpoint health probe failure, a pre-v4 client admitted instead of receiving actionable HTTP 426, or npm consumer install/doctor failure on the v4-only dist.",
19370
19448
  rollback: {
19371
19449
  independent: true,
19372
- mechanism: "npm dist-tag latest -> 4.5.207 and redeploy the Hub Lambda from tag v4.5.207 (55e3ac7b8df0); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
19373
- v3Target: "v4.5.207 (@mutmutco/cli@4.5.207, tag commit 55e3ac7b8df0 \u2014 last known-good release carrying the repo-index v4-only contract)"
19450
+ mechanism: "npm dist-tag latest -> 4.5.209 and redeploy the Hub Lambda from tag v4.5.209 (2449709d554c); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
19451
+ v3Target: "v4.5.209 (@mutmutco/cli@4.5.209, tag commit 2449709d554c \u2014 last known-good release carrying the repo-index v4-only contract)"
19374
19452
  }
19375
19453
  },
19376
19454
  {
@@ -58008,6 +58086,7 @@ var STALE_HINT = `(${DISCOVERY_HINT}). If you expected this command to exist, yo
58008
58086
  var lastParseErrorKind = "other";
58009
58087
  var lastUnknownCommand;
58010
58088
  var lastParseErrorConflict = false;
58089
+ var lastParseHintOwnsGuess = false;
58011
58090
  function parseInvalidChoiceError(plain) {
58012
58091
  const m = /option '([^']+)' argument '([^']*)' is invalid\. Allowed choices are ([^.]+)\./.exec(plain);
58013
58092
  if (!m) return void 0;
@@ -58076,6 +58155,12 @@ function resolveParseHint() {
58076
58155
  const parentPath = parent ? canonicalPathFor(commandPath3(parent)) ?? commandPath3(parent) : void 0;
58077
58156
  const guide = unknownCommandDomainGuide(parentPath, lastUnknownCommand);
58078
58157
  if (guide) return `(${guide.hint}. ${DISCOVERY_HINT})`;
58158
+ const claimCmd = resolveCommandFromArgv(program2, ["board", "claim"]);
58159
+ const workboard = claimCmd ? workboardClaimRecovery(lastUnknownCommand, process.argv.slice(2), allCommandPaths(), commandOwnLongFlags(claimCmd)) : void 0;
58160
+ if (workboard) {
58161
+ lastParseHintOwnsGuess = true;
58162
+ return `(${workboard.hint} ${DISCOVERY_HINT})`;
58163
+ }
58079
58164
  const candidates = unknownCommandCandidates(parent, allCommandPaths());
58080
58165
  const tail = unknownCommandTail(process.argv.slice(2), lastUnknownCommand);
58081
58166
  const path3 = lastUnknownCommand ? suggestCommandPath(lastUnknownCommand, candidates, tail) : void 0;
@@ -58134,7 +58219,7 @@ function envelopeAwareWriteErr(str2) {
58134
58219
  return;
58135
58220
  }
58136
58221
  const resolvedHint = resolveParseHint();
58137
- if (lastParseErrorKind === "unknown-command" && (resolvedHint === STALE_HINT || resolvedHint === `(${DISCOVERY_HINT})`)) {
58222
+ if (lastParseErrorKind === "unknown-command" && (lastParseHintOwnsGuess || resolvedHint === STALE_HINT || resolvedHint === `(${DISCOVERY_HINT})`)) {
58138
58223
  pendingHumanParseError = pendingHumanParseError?.replace(/\n\(Did you mean [^)]+\?\)/g, "");
58139
58224
  }
58140
58225
  const hint = str2.replace(PARSE_HINT_SENTINEL, resolvedHint);
@@ -59427,6 +59512,7 @@ function printHouseRootHelp(house) {
59427
59512
  }
59428
59513
  resolveVerbAliasShim(process.argv);
59429
59514
  resolveHouseShim(process.argv);
59515
+ normalizeBoardClaimIssueArgv(process.argv);
59430
59516
  program2.parseAsync(process.argv).then(() => finishCliRun()).catch((e) => failGraceful(e.message));
59431
59517
  // Annotate the CommonJS export names for ESM import in node:
59432
59518
  0 && (module.exports = {
@@ -59437,11 +59523,13 @@ program2.parseAsync(process.argv).then(() => finishCliRun()).catch((e) => failGr
59437
59523
  commandOwnLongFlags,
59438
59524
  envHealLockPath,
59439
59525
  isOrgRegisteredRepo,
59526
+ normalizeBoardClaimIssueArgv,
59440
59527
  parseInvalidChoiceError,
59441
59528
  positionalTargetForm,
59442
59529
  registryClientDeps,
59443
59530
  repoSlug,
59444
59531
  suggestCommandPath,
59445
59532
  unknownCommandCandidates,
59446
- unknownCommandTail
59533
+ unknownCommandTail,
59534
+ workboardClaimRecovery
59447
59535
  });
package/cli/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/cli",
3
- "version": "4.5.207",
3
+ "version": "4.5.209",
4
4
  "description": "MMI Future CLI — the org dev toolbox and shared cross-IDE engine for every registry-declared MMI coding surface.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/codex-plugin",
3
- "version": "4.5.207",
3
+ "version": "4.5.209",
4
4
  "description": "MMI workflow skills and org gates delivery.",
5
5
  "author": {
6
6
  "name": "MMI Future",
@@ -36,7 +36,7 @@ The bible for the MM open design system; every agent doing UI, design or MM Arti
36
36
  Four owner decisions (2026-10-25T15:35:52Z):
37
37
 
38
38
  1. **Doc vs. app kit — add a Document Design System too.** Keep the MM-Work Atomic Design System (`3a5c79df-5274-40ad-a1b5-a75e67a74dac`) for MM-Work and module app UI (and as the fallback for now), and add a dedicated Document/Editorial Design System Artifact in Live Docs for reports, checklists, decks and client documents made by Junior or agents.
39
- 2. **Where to save — local HTML for dev, Live Docs for shared.** Coding agents build and open local `.html` MM Artifacts (`node artifacts/review/review.mjs <folder> --standalone [<out.html>] [--open]`) for fast iteration, and publish to Live Docs only for a shared deliverable, an A/B decision canvas or a Design System. Junior inside MM-Work saves directly to Live Docs.
39
+ 2. **Where to save — local HTML for dev, Live Docs for shared.** Coding agents build and open local `.html` MM Artifacts for fast iteration — interactive owner A/B reviews with `node artifacts/review/review.mjs <folder> --open` on the live loopback HTTP review server (`http://127.0.0.1:<port>/` with `Send answers`), and offline HTML previews/exports or SSR pre-render verification (`impeccable detect --json`) with `node artifacts/review/review.mjs <folder> --standalone [<out.html>]` — and publish to Live Docs only for a shared deliverable, an A/B decision canvas or a Design System. Junior inside MM-Work saves directly to Live Docs.
40
40
  3. **Artifact shape — single HTML by default, Canvas for A/B.** A single self-contained HTML view for documents, checklists and single-screen work; a multi-board spatial Canvas only for A/B choices or `1440`/`1024`/`390` side-by-side comparisons.
41
41
  4. **Kit binding — Live Docs hosts kits; npm only for MM-Work.** Every Design System Artifact in Live Docs stores its tokens/CSS/components and `DESIGN.md` so any HTML artifact can bind to it (`kit: { id, version }`); only the MM-Work app design system is also exported as `@mutmutco/mmwork-ds`, because the MM-Work app and the 10 suite modules compile against it.
42
42
 
@@ -114,11 +114,17 @@ requests like this should follow this structure, not prose guide."
114
114
  Option C, each its own full-resolution `1440x900` live HTML board in one MM Artifact A/B canvas
115
115
  (Part 3 rules: content-only `Ctrl + Mousewheel` zoom, 1:1 or side-by-side live comparison). Open
116
116
  the verified canvas in the browser automatically with
117
- `node artifacts/review/review.mjs <folder> --standalone --open`. Spawn a dedicated, fresh
117
+ `node artifacts/review/review.mjs <folder> --open`, which serves it over the live loopback HTTP
118
+ review server (`http://127.0.0.1:<port>/`) so the owner's `Send answers` posts straight back to
119
+ `POST /answers`. Never open a `--standalone` `file://` export (`Download answers.json`) for an
120
+ interactive owner A/B decision: `--standalone [<out.html>]` is only for offline previews/exports
121
+ and SSR detector checks. Spawn a dedicated, fresh
118
122
  `designer` subagent for each distinct design task (item 3); never reuse a busy designer seat.
119
123
  - **Stage 2 — the owner chooses visually on the A/B canvas.** Wait while the owner inspects the
120
124
  live HTML alternatives, zooms into details and picks the preferred design or asks for
121
- adjustments. Record the canvas choice ID and the owner-decision reference.
125
+ adjustments, then presses `Send answers` on the live review server page; `review.mjs` writes
126
+ `answers.json` into the canvas folder and exits. Record the canvas choice ID and the
127
+ owner-decision reference.
122
128
  - **Stage 3 — atomic replacement in the kit source.** Only AFTER the owner picks on the A/B canvas,
123
129
  build the chosen design into the source folder of packages/mmwork-ds in mutmutco/MM-Work,
124
130
  **atomically replacing** every other legacy or competing variant of that piece across the design
@@ -137,7 +143,7 @@ requests like this should follow this structure, not prose guide."
137
143
 
138
144
  UI and design verification uses `@mutmutco/mmwork-ds` (`mmwork-check-ui`) plus Impeccable on every design task: inspect the toolkit for applicable capabilities, work directly on the live app, and use our own MM Artifacts A/B canvas only when an owner A/B choice is needed. Functional journeys, where separately permitted, stay opt-in `workflow_dispatch`-only and never act as design checks.
139
145
 
140
- Front-load Impeccable before any UI or MM Artifact authoring: `impeccable context --target <path>`, `DESIGN.md` + the `design.json` sidecar in `.impeccable`, `.impeccable/config.json` (`hook.enabled: true`), `reference/craft-floor.md` + `reference/operate.md`, and `impeccable detect --json <target>`. Local/canvas MM Artifacts (`mm-artifact` v3 format) are checked and opened with one command: `node artifacts/review/review.mjs <folder> --standalone [<out.html>] [--open]`, which runs `check.mjs`, `check-ui.mjs` and `geometry.mjs`, pre-renders the board in `node:vm` (`ReactDOMServer.renderToStaticMarkup` into `#root`), runs `impeccable detect --json` on that rendered HTML, and opens it in the browser with `--open`.
146
+ Front-load Impeccable before any UI or MM Artifact authoring: `impeccable context --target <path>`, `DESIGN.md` + the `design.json` sidecar in `.impeccable`, `.impeccable/config.json` (`hook.enabled: true`), `reference/craft-floor.md` + `reference/operate.md`, and `impeccable detect --json <target>`. Local/canvas MM Artifacts (`mm-artifact` v3 format) are checked with one command, `node artifacts/review/review.mjs <folder>`, which runs `check.mjs`, `check-ui.mjs` and `geometry.mjs`, pre-renders the board in `node:vm` (`ReactDOMServer.renderToStaticMarkup` into `#root`) and runs `impeccable detect --json` on that rendered HTML. Interactive owner A/B reviews use `node artifacts/review/review.mjs <folder> --open`, which serves the canvas over the live loopback HTTP review server (`http://127.0.0.1:<port>/`) where the owner presses `Send answers`; `--standalone [<out.html>]` is only for offline HTML previews/exports and SSR pre-render verification, never for an interactive owner decision.
141
147
 
142
148
  Impeccable v4.7.0 (engine v0.1.16) workflow; CLI verbs and agent playbooks are distinct:
143
149
 
@@ -51,11 +51,14 @@ design work follows one harmonized **Front-Loaded Impeccable v4.7.0 + MM Artifac
51
51
  `DESIGN.md` plus its `design.json` sidecar in `.impeccable`, shared `.impeccable/config.json`
52
52
  (`hook.enabled: true`), `reference/craft-floor.md` + `reference/operate.md`, and
53
53
  `impeccable detect --json <target>`.
54
- - **MM Artifacts** (local/canvas packs in the `mm-artifact` v3 format) use one command:
55
- `node artifacts/review/review.mjs <folder> --standalone [<out.html>] [--open]`. It runs `check.mjs`,
56
- `check-ui.mjs` and `geometry.mjs`, pre-renders the board in `node:vm` via
57
- `ReactDOMServer.renderToStaticMarkup` into `#root`, runs `impeccable detect --json` on that
58
- SSR-rendered HTML, and opens the result in the browser with `--open`.
54
+ - **MM Artifacts** (local/canvas packs in the `mm-artifact` v3 format) use one command,
55
+ `node artifacts/review/review.mjs <folder>`. It runs `check.mjs`, `check-ui.mjs` and
56
+ `geometry.mjs`, pre-renders the board in `node:vm` via `ReactDOMServer.renderToStaticMarkup` into
57
+ `#root` and runs `impeccable detect --json` on that SSR-rendered HTML. Interactive owner A/B
58
+ reviews use `node artifacts/review/review.mjs <folder> --open`: it serves the canvas over the live
59
+ loopback HTTP review server (`http://127.0.0.1:<port>/`) and the owner's `Send answers` posts back
60
+ to `POST /answers`. `--standalone [<out.html>]` is only for offline HTML previews/exports and SSR
61
+ pre-render verification, never for an interactive owner decision.
59
62
  - **Live Docs** (`Canlı belgeler` viewer) carry the living references, including the live
60
63
  design-system artifact `3a5c79df-5274-40ad-a1b5-a75e67a74dac`.
61
64
  - **Atomic Design Kit** (`@mutmutco/mmwork-ds`): kit pieces and tokens only, checked with `mmwork-check-ui`.
@@ -73,7 +76,7 @@ How the five pillars fit together (owner, 2026-10-25):
73
76
  Four owner decisions (2026-10-25T15:35:52Z):
74
77
 
75
78
  1. **Doc vs. app kit — add a Document Design System too.** Keep the MM-Work Atomic Design System (`3a5c79df-5274-40ad-a1b5-a75e67a74dac`) for MM-Work and module app UI (and as the fallback for now), and add a dedicated Document/Editorial Design System Artifact in Live Docs for reports, checklists, decks and client documents made by Junior or agents.
76
- 2. **Where to save — local HTML for dev, Live Docs for shared.** Coding agents build and open local `.html` MM Artifacts (`node artifacts/review/review.mjs <folder> --standalone [<out.html>] [--open]`) for fast iteration, and publish to Live Docs only for a shared deliverable, an A/B decision canvas or a Design System. Junior inside MM-Work saves directly to Live Docs.
79
+ 2. **Where to save — local HTML for dev, Live Docs for shared.** Coding agents build and open local `.html` MM Artifacts for fast iteration — interactive owner A/B reviews with `node artifacts/review/review.mjs <folder> --open` on the live loopback HTTP review server (`http://127.0.0.1:<port>/` with `Send answers`), and offline HTML previews/exports or SSR pre-render verification (`impeccable detect --json`) with `node artifacts/review/review.mjs <folder> --standalone [<out.html>]` — and publish to Live Docs only for a shared deliverable, an A/B decision canvas or a Design System. Junior inside MM-Work saves directly to Live Docs.
77
80
  3. **Artifact shape — single HTML by default, Canvas for A/B.** A single self-contained HTML view for documents, checklists and single-screen work; a multi-board spatial Canvas only for A/B choices or `1440`/`1024`/`390` side-by-side comparisons.
78
81
  4. **Kit binding — Live Docs hosts kits; npm only for MM-Work.** Every Design System Artifact in Live Docs stores its tokens/CSS/components and `DESIGN.md` so any HTML artifact can bind to it (`kit: { id, version }`); only the MM-Work app design system is also exported as `@mutmutco/mmwork-ds`, because the MM-Work app and the 10 suite modules compile against it.
79
82
 
@@ -209,11 +212,17 @@ requests like this should follow this structure, not prose guide."
209
212
  Option C, each its own full-resolution `1440x900` live HTML board in one MM Artifact A/B canvas
210
213
  (Part 3 rules: content-only `Ctrl + Mousewheel` zoom, 1:1 or side-by-side live comparison). Open
211
214
  the verified canvas in the browser automatically with
212
- `node artifacts/review/review.mjs <folder> --standalone --open`. Spawn a dedicated, fresh
215
+ `node artifacts/review/review.mjs <folder> --open`, which serves it over the live loopback HTTP
216
+ review server (`http://127.0.0.1:<port>/`) so the owner's `Send answers` posts straight back to
217
+ `POST /answers`. Never open a `--standalone` `file://` export (`Download answers.json`) for an
218
+ interactive owner A/B decision: `--standalone [<out.html>]` is only for offline previews/exports
219
+ and SSR detector checks. Spawn a dedicated, fresh
213
220
  `designer` subagent for each distinct design task (item 3); never reuse a busy designer seat.
214
221
  - **Stage 2 — the owner chooses visually on the A/B canvas.** Wait while the owner inspects the
215
222
  live HTML alternatives, zooms into details and picks the preferred design or asks for
216
- adjustments. Record the canvas choice ID and the owner-decision reference.
223
+ adjustments, then presses `Send answers` on the live review server page; `review.mjs` writes
224
+ `answers.json` into the canvas folder and exits. Record the canvas choice ID and the
225
+ owner-decision reference.
217
226
  - **Stage 3 — atomic replacement in the kit source.** Only AFTER the owner picks on the A/B canvas,
218
227
  build the chosen design into the source folder of packages/mmwork-ds in mutmutco/MM-Work,
219
228
  **atomically replacing** every other legacy or competing variant of that piece across the design