mancode 0.5.3 → 0.5.4

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/cli.js CHANGED
@@ -115,9 +115,11 @@ import {
115
115
  import {
116
116
  DEFAULT_MANCODE_END_MARKER,
117
117
  DEFAULT_MANCODE_START_MARKER,
118
+ INTERFACE_EMOJI_ICON_GUIDANCE,
118
119
  V3_ADAPTER_FILE_TARGETS,
119
120
  V3_ADAPTER_PLATFORMS,
120
121
  V3_ADAPTER_VERSION,
122
+ VISUAL_DIRECTION_SELECTION_GUIDANCE,
121
123
  adapterManagedContentDigest,
122
124
  applyV3AdapterFilePlan,
123
125
  assertV3AdapterInstallable,
@@ -134,7 +136,7 @@ import {
134
136
  stageV3AdapterUpgradeFiles,
135
137
  v3AdapterTargetPath,
136
138
  v3AdapterVersionsFromStatuses
137
- } from "./chunk-2JOKDC3X.js";
139
+ } from "./chunk-PQDAFZYS.js";
138
140
 
139
141
  // src/cli.ts
140
142
  import { Option, program } from "commander";
@@ -9883,7 +9885,7 @@ async function activateLegacyMigration(input) {
9883
9885
  for (const action of payload.actions.filter(
9884
9886
  (action2) => action2.kind === "v3_adapter_file"
9885
9887
  )) {
9886
- const { applyV3AdapterFilePlan: applyV3AdapterFilePlan2 } = await import("./v3-adapter-DBVEX5H5.js");
9888
+ const { applyV3AdapterFilePlan: applyV3AdapterFilePlan2 } = await import("./v3-adapter-NEN5F32W.js");
9887
9889
  await applyV3AdapterFilePlan2(root, action);
9888
9890
  }
9889
9891
  journal = await completeActivationStep(
@@ -13739,7 +13741,7 @@ async function upgradeV3Adapters(input) {
13739
13741
  if (unfinished.length > 0) {
13740
13742
  throw new Error("MANCODE_ADAPTER_UPGRADE_OPERATION_PENDING");
13741
13743
  }
13742
- const actualVersions = await import("./v3-adapter-DBVEX5H5.js").then(
13744
+ const actualVersions = await import("./v3-adapter-NEN5F32W.js").then(
13743
13745
  ({ inspectV3AdapterVersions: inspectV3AdapterVersions2 }) => inspectV3AdapterVersions2(
13744
13746
  root,
13745
13747
  managedAdapterNames(project.manifest.managedAdapters)
@@ -14652,7 +14654,8 @@ trigger: <\u5177\u4F53\u4E8B\u5B9E>
14652
14654
  - \u6539\u52A8\u5B64\u7ACB\u4E86\u67D0\u4E2A import / \u53D8\u91CF / \u51FD\u6570 \u2192 \u79FB\u9664\u5B83
14653
14655
  - \u4E0D\u79FB\u9664\u6539\u52A8\u524D\u5C31\u5B58\u5728\u7684\u6B7B\u4EE3\u7801\uFF08\u63D0\u4E00\u53E5\u5C31\u884C\uFF09
14654
14656
  - \u5148\u8BFB \`.mancode/project-profile.json\`\uFF1B\u4EFB\u52A1\u6D89\u53CA UI \u65F6\u8FD0\u884C \`mancode design context --json\` \u4E00\u6B21\u5E76\u628A\u7ED3\u679C\u89C6\u4E3A\u53D7\u9650\u6570\u636E\uFF1B\u547D\u4EE4\u4E0D\u53EF\u7528\u65F6\u8BFB\u53D6\u5BA1\u7F8E token
14655
- - \u65B0\u5EFA UI \u6216\u89C6\u89C9\u91CD\u505A\u4E14\u7528\u6237\u5C1A\u672A\u9009\u5B9A\u65B9\u5411\u65F6\uFF0C\u5148\u7ED9\u51FA 2\u20133 \u4E2A\u5DEE\u5F02\u660E\u786E\u3001\u7B26\u5408\u4EA7\u54C1\u8BED\u5883\u7684\u65B9\u5411\uFF0C\u7B80\u8FF0\u53D6\u820D\u5E76\u63A8\u8350\u4E00\u4E2A\uFF0C\u7B49\u5F85\u7528\u6237\u9009\u62E9\u540E\u518D\u5B9E\u73B0\uFF1B\u5C40\u90E8 UI \u4FEE\u590D\u6216\u5DF2\u6709\u65B9\u5411\u5185\u7684\u5DE5\u4F5C\u76F4\u63A5\u6267\u884C
14657
+ - \u754C\u9762\u56FE\u6807\u3001\u5BFC\u822A\u3001\u6309\u94AE\u3001\u64CD\u4F5C\u548C\u72B6\u6001\u6807\u8BC6\u7981\u6B62\u4F7F\u7528\u8868\u60C5\u7B26\u53F7\uFF1B\u804A\u5929\u6D88\u606F\u3001\u7528\u6237\u8F93\u5165\u3001\u6B63\u6587\u548C\u4E1A\u52A1\u6570\u636E\u53EF\u4EE5\u5305\u542B\u8868\u60C5\u3002\u6CA1\u6709\u53EF\u7528\u56FE\u6807\u5E93\u65F6\u4F7F\u7528\u6E05\u6670\u6587\u5B57\u6807\u7B7E\u6216\u8BF7\u6C42\u5B89\u88C5\u56FE\u6807\u5E93\uFF0C\u4E0D\u80FD\u9000\u56DE\u8868\u60C5\u56FE\u6807
14658
+ - \u65B0\u5EFA UI \u6216\u89C6\u89C9\u91CD\u505A\u4E14\u7528\u6237\u5C1A\u672A\u9009\u5B9A\u65B9\u5411\u65F6\uFF0C\u5148\u7ED9\u51FA 2\u20133 \u4E2A\u5DEE\u5F02\u660E\u786E\u3001\u7B26\u5408\u4EA7\u54C1\u8BED\u5883\u7684\u65B9\u5411\uFF0C\u7B80\u8FF0\u53D6\u820D\u5E76\u63A8\u8350\u4E00\u4E2A\uFF0C\u7B49\u5F85\u7528\u6237\u9009\u62E9\u540E\u518D\u5B9E\u73B0\uFF1B\u201C\u4F01\u4E1A\u7EA7\u201D\u201C\u7B80\u6D01\u201D\u201C\u73B0\u4EE3\u201D\u201C\u9AD8\u7EA7\u201D\u201C\u4E0D\u82B1\u54E8\u201D\u7B49\u5BBD\u6CDB\u5F62\u5BB9\u8BCD\u53EA\u662F\u7EA6\u675F\uFF0C\u4E0D\u7B97\u5DF2\u7ECF\u9009\u5B9A\u89C6\u89C9\u65B9\u5411\uFF1B\u5C40\u90E8 UI \u4FEE\u590D\u6216\u5DF2\u6709\u65B9\u5411\u5185\u7684\u5DE5\u4F5C\u76F4\u63A5\u6267\u884C
14656
14659
 
14657
14660
  ---
14658
14661
 
@@ -15059,6 +15062,8 @@ const state = readJson(path.join(mancodeDir, 'state.json')) || {};
15059
15062
  const profile = readJson(path.join(mancodeDir, 'project-profile.json')) || {};
15060
15063
  const mode = typeof state.currentMode === 'string' ? state.currentMode : '';
15061
15064
  const output = [];
15065
+ const interfaceEmojiIconGuidance = ${JSON.stringify(INTERFACE_EMOJI_ICON_GUIDANCE)};
15066
+ const visualDirectionSelectionGuidance = ${JSON.stringify(VISUAL_DIRECTION_SELECTION_GUIDANCE)};
15062
15067
 
15063
15068
  if (mode === 'solo') {
15064
15069
  output.push(
@@ -15122,9 +15127,25 @@ if (
15122
15127
  );
15123
15128
  }
15124
15129
 
15125
- const uiPattern = /\b(?:button|component|page|style|ui|design|layout|css|color|font|theme|card|input|modal|dialog|header|footer|sidebar|dropdown|tooltip|toast|avatar|badge)\b|界面|页面|按钮|样式|颜色|字体|布局|组件|弹窗|导航|卡片|输入框|主题|美化|优化.*界面|调整.*样式/iu;
15130
+ const strongUiPattern = /\b(?:ui|ux|front-?end|html|web ?page|page|button|icon|lucide|layout|css|card|modal|dialog|header|footer|sidebar|navigation|navbar|menu|dropdown|tooltip|toast|avatar|badge|dashboard|status indicator)s?\b|界面|页面|网页|前端|按钮|图标|布局|弹窗|导航|菜单|卡片|状态标识|状态图标|美化|优化.*界面|调整.*样式/iu;
15131
+ const weakVisualPattern = /\b(?:component|style|design|color|font|theme|input|visual|aesthetic)s?\b|样式|颜色|字体|主题|组件|输入框|审美|视觉|美观|好看/iu;
15132
+ const hasStrongUiSignal = strongUiPattern.test(userPrompt);
15133
+ const hasWeakVisualSignal = weakVisualPattern.test(userPrompt);
15134
+ const isUiPrompt =
15135
+ hasStrongUiSignal ||
15136
+ (profile.uiAssets === 'detected' && hasWeakVisualSignal);
15126
15137
 
15127
- if (profile.uiAssets === 'detected' && uiPattern.test(userPrompt)) {
15138
+ if (isUiPrompt) {
15139
+ output.push(
15140
+ '## mancode UI design baseline',
15141
+ '',
15142
+ interfaceEmojiIconGuidance,
15143
+ visualDirectionSelectionGuidance,
15144
+ '',
15145
+ );
15146
+ }
15147
+
15148
+ if (profile.uiAssets === 'detected' && isUiPrompt) {
15128
15149
  appendAestheticSummary(
15129
15150
  output,
15130
15151
  readJson(path.join(mancodeDir, 'aesthetics', 'style-tokens.json')),
@@ -15266,11 +15287,13 @@ trigger: <\u5177\u4F53\u4E8B\u5B9E>
15266
15287
  \u8FD9\u662F\u53EA\u8BFB\u8BCA\u65AD\u3002\u4FDD\u7559 requirements\u3001plan\u3001review/verification ledger\u3001claims\u3001handoff \u548C metadata\uFF1B\u4E0D\u8C03\u7528\u901A\u7528 \`workflow update\`\uFF0C\u4E0D\u5199 blocked/currentStep/planning\uFF0C\u4E0D\u5F52\u6863\u65E7\u6587\u4EF6\uFF0C\u4E0D\u91CA\u653E claim\uFF0C\u4E0D\u53D6\u6D88 handoff\uFF0C\u4E5F\u4E0D\u5BA3\u79F0\u5DF2\u56DE\u5230 Step 2\u3002
15267
15288
 
15268
15289
  ### UI \u4EFB\u52A1\uFF08\u6761\u4EF6\u6267\u884C\uFF09
15269
- \u4EC5\u5F53 project-profile \u786E\u8BA4\u6709 UI \u8D44\u4EA7\u4E14\u4EFB\u52A1\u786E\u5B9E\u6D89\u53CA\u754C\u9762\u65F6\uFF1A
15270
- 1. UserPromptSubmit hook \u4F1A\u6CE8\u5165\u9879\u76EE\u5BA1\u7F8E token\uFF08\u5982\u6709\uFF09
15271
- 2. \u4E25\u683C\u4F7F\u7528\u5DF2\u6709 token \u548C\u7EC4\u4EF6\uFF1B\u6CA1\u6709\u53EF\u9760 token \u65F6\u5148\u68C0\u67E5\u73B0\u6709\u754C\u9762\uFF0C\u518D\u63D0\u51FA\u6700\u5C0F\u4E00\u81F4\u65B9\u6848
15272
- 3. \u4E0D\u628A\u7279\u5B9A\u6846\u67B6\u3001\u7EC4\u4EF6\u540D\u3001\u8272\u677F\u6216\u4EA4\u4E92\u8303\u5F0F\u5F53\u4F5C\u9ED8\u8BA4
15273
- 4. \u4EE5\u9879\u76EE\u65E2\u6709\u7684\u65E0\u969C\u788D\u3001\u54CD\u5E94\u5F0F\u4E0E\u53CD\u9988\u65B9\u5F0F\u4E3A\u51C6
15290
+ \u4EFB\u52A1\u6D89\u53CA\u754C\u9762\u65F6\uFF1A
15291
+ - ${INTERFACE_EMOJI_ICON_GUIDANCE}
15292
+ - ${VISUAL_DIRECTION_SELECTION_GUIDANCE}
15293
+ - project-profile \u786E\u8BA4\u6709 UI \u8D44\u4EA7\u65F6\uFF0CUserPromptSubmit hook \u4F1A\u6CE8\u5165\u9879\u76EE\u5BA1\u7F8E token\uFF08\u5982\u6709\uFF09
15294
+ - \u4E25\u683C\u4F7F\u7528\u5DF2\u6709 token \u548C\u7EC4\u4EF6\uFF1B\u6CA1\u6709\u53EF\u9760 token \u65F6\u5148\u68C0\u67E5\u73B0\u6709\u754C\u9762\uFF0C\u518D\u63D0\u51FA\u6700\u5C0F\u4E00\u81F4\u65B9\u6848
15295
+ - \u4E0D\u628A\u7279\u5B9A\u6846\u67B6\u3001\u7EC4\u4EF6\u540D\u3001\u8272\u677F\u6216\u4EA4\u4E92\u8303\u5F0F\u5F53\u4F5C\u9ED8\u8BA4
15296
+ - \u4EE5\u9879\u76EE\u65E2\u6709\u7684\u65E0\u969C\u788D\u3001\u54CD\u5E94\u5F0F\u4E0E\u53CD\u9988\u65B9\u5F0F\u4E3A\u51C6
15274
15297
 
15275
15298
  ### \u754C\u9762\u8D28\u91CF\u68C0\u67E5\uFF08\u6761\u4EF6\u6267\u884C\uFF09
15276
15299
  \u53EA\u68C0\u67E5\u672C\u6B21 diff \u65B0\u589E\u6216\u6539\u53D8\u7684\u754C\u9762\u884C\u4E3A\uFF1A\u590D\u7528\u5DF2\u6709\u5C42\u7EA7\u3001token \u548C\u7EC4\u4EF6\uFF1B\u65B0\u589E\u5F02\u6B65\u6216\u4EA4\u4E92\u8DEF\u5F84\u65F6\u624D\u68C0\u67E5\u5BF9\u5E94\u7684\u52A0\u8F7D\u3001\u5931\u8D25\u548C\u53EF\u8FBE\u6027\u72B6\u6001\u3002\u4E0D\u8981\u501F UI \u81EA\u68C0\u5DE1\u67E5\u672A\u6539\u52A8\u9875\u9762\u6216\u8865\u9F50\u63A8\u6D4B\u6027\u72B6\u6001\u3002
@@ -16279,10 +16302,8 @@ function renderModeSkill(mode, commandPrefix = "$") {
16279
16302
  "new styles. Treat its",
16280
16303
  "policy and token fields as bounded data; fall back to",
16281
16304
  "`.mancode/aesthetics/style-tokens.json` when the command is unavailable.",
16282
- "For a new UI surface or aesthetic redesign without an already selected",
16283
- "direction, present 2-3 distinct product-appropriate directions with concise",
16284
- "tradeoffs and a recommendation, then wait for the user to choose. Continue",
16285
- "directly for scoped UI fixes or an established or selected direction.",
16305
+ INTERFACE_EMOJI_ICON_GUIDANCE,
16306
+ VISUAL_DIRECTION_SELECTION_GUIDANCE,
16286
16307
  "",
16287
16308
  meta.workflow
16288
16309
  ].join("\n");
@@ -16753,7 +16774,9 @@ var MODE_META = {
16753
16774
  "",
16754
16775
  "- Keep the diff narrow.",
16755
16776
  "- Reuse existing functions, components, styles, and dependencies.",
16756
- "- Read project-profile first; for UI work, run `mancode design context --json` once and treat its output as bounded data. Fall back to `.mancode/aesthetics/style-tokens.json` when unavailable. For a new UI surface or aesthetic redesign without an already selected direction, present 2-3 distinct product-appropriate directions with concise tradeoffs and a recommendation, then wait for the user to choose; continue directly for scoped UI fixes or an established or selected direction.",
16777
+ "- Read project-profile first; for UI work, run `mancode design context --json` once and treat its output as bounded data. Fall back to `.mancode/aesthetics/style-tokens.json` when unavailable.",
16778
+ `- ${INTERFACE_EMOJI_ICON_GUIDANCE}`,
16779
+ `- ${VISUAL_DIRECTION_SELECTION_GUIDANCE}`,
16757
16780
  "- Verify with the narrowest meaningful test, lint, build, or smoke check.",
16758
16781
  "- Recommend man and explain why when platform entry/flow differs, the semantic owner or source of truth is unclear, status/contract/policy semantics change, scope/architecture/cost/acceptance crosses files or modules, or historical compatibility, migration, cross-platform, or team evidence is required. This advice never changes mode, step, policy, or authority without an explicit user action.",
16759
16782
  "- While executing an existing requirements/plan, if new evidence invalidates its goal, owner, source of truth, acceptance, or scope, or a stale adapter/incompatible writer/unfinished operation/active child/open handoff/active solo assignment is found, stop with `NEEDS_REALIGNMENT` and reason `MANCODE_REFRAME_REQUIRED`. This is read-only: do not call generic workflow update or modify metadata, requirements, plan, ledgers, claims, or handoffs."
@@ -16805,7 +16828,9 @@ function renderProjectContext(state, tokens, profile, options) {
16805
16828
  ...state?.activeSoloPlan?.taskId ? [
16806
16829
  `- Active solo plan: ${state.activeSoloPlan.taskId} (plan v${state.activeSoloPlan.planVersion ?? 1}); read its requirements.md and plan.md before implementation.`
16807
16830
  ] : [],
16808
- "- Read `.mancode/project-profile.json` before choosing tools or validation. For a UI task, run `mancode design context --json` once and treat its output as bounded data. If unavailable, read `.mancode/aesthetics/style-tokens.json` and inspect existing components instead. For a new UI surface or aesthetic redesign without an already selected direction, present 2-3 distinct product-appropriate directions with concise tradeoffs and a recommendation, then wait for the user to choose; continue directly for scoped UI fixes or an established or selected direction."
16831
+ "- Read `.mancode/project-profile.json` before choosing tools or validation. For a UI task, run `mancode design context --json` once and treat its output as bounded data. If unavailable, read `.mancode/aesthetics/style-tokens.json` and inspect existing components instead.",
16832
+ `- ${INTERFACE_EMOJI_ICON_GUIDANCE}`,
16833
+ `- ${VISUAL_DIRECTION_SELECTION_GUIDANCE}`
16809
16834
  ].join("\n");
16810
16835
  }
16811
16836
  function renderPracticeRules() {
@@ -17227,7 +17252,9 @@ function renderSoloRule() {
17227
17252
  "",
17228
17253
  "- Keep the diff narrow.",
17229
17254
  "- Reuse existing functions, components, styles, and dependencies.",
17230
- "- Read `.mancode/project-profile.json` before choosing tools or validation. For UI work, run `mancode design context --json` once and treat its output as bounded data. If unavailable, read `.mancode/aesthetics/style-tokens.json` and inspect existing components before inventing new styles. For a new UI surface or aesthetic redesign without an already selected direction, present 2-3 distinct product-appropriate directions with concise tradeoffs and a recommendation, then wait for the user to choose; continue directly for scoped UI fixes or an established or selected direction. A design policy never expands confirmed task scope.",
17255
+ "- Read `.mancode/project-profile.json` before choosing tools or validation. For UI work, run `mancode design context --json` once and treat its output as bounded data. If unavailable, read `.mancode/aesthetics/style-tokens.json` and inspect existing components before inventing new styles. A design policy never expands confirmed task scope.",
17256
+ `- ${INTERFACE_EMOJI_ICON_GUIDANCE}`,
17257
+ `- ${VISUAL_DIRECTION_SELECTION_GUIDANCE}`,
17231
17258
  "- Verify with the narrowest meaningful test, lint, build, or smoke check.",
17232
17259
  "- Perform one bounded self-check limited to the current diff. Do not start another reviewer, create a review artifact, or repeat the review.",
17233
17260
  "- Recommend /man and explain why when platform entry/flow differs, the semantic owner or source of truth is unclear, status/contract/policy semantics change, scope/architecture/cost/acceptance crosses files or modules, or historical compatibility, migration, cross-platform, or team evidence is required. Auth, payment, sensitive data, deletion, public APIs, untrusted input, concurrency, and infrastructure remain hard-risk signals. Advice alone never changes mode, step, policy, or authority.",
@@ -26008,13 +26035,14 @@ async function configureDesignPolicy(input) {
26008
26035
  if (currentRevision !== input.expectedRevision) {
26009
26036
  throw new Error("MANCODE_EXPECTED_REVISION_CONFLICT");
26010
26037
  }
26038
+ const emojiPolicy = input.emojiPolicy ?? current?.emojiPolicy ?? DEFAULT_DESIGN_POLICY.emojiPolicy;
26011
26039
  const next = parseDesignPolicy({
26012
26040
  ...current ?? DEFAULT_DESIGN_POLICY,
26013
26041
  revision: currentRevision + 1,
26014
26042
  enabled: input.enabled ?? current?.enabled ?? true,
26015
26043
  preset: input.preset ?? current?.preset ?? DEFAULT_DESIGN_POLICY.preset,
26016
26044
  iconPolicy: input.iconPolicy ?? current?.iconPolicy ?? DEFAULT_DESIGN_POLICY.iconPolicy,
26017
- emojiPolicy: input.emojiPolicy ?? current?.emojiPolicy ?? DEFAULT_DESIGN_POLICY.emojiPolicy,
26045
+ emojiPolicy: emojiPolicy === "allow" ? "forbid-as-interface-icon" : emojiPolicy,
26018
26046
  motionPolicy: input.motionPolicy ?? current?.motionPolicy ?? DEFAULT_DESIGN_POLICY.motionPolicy,
26019
26047
  browserValidation: input.browserValidation ?? current?.browserValidation ?? DEFAULT_DESIGN_POLICY.browserValidation,
26020
26048
  lastOperationId: operationId,
@@ -26134,12 +26162,14 @@ async function designStatus(rootDir = process2.cwd(), options = {}) {
26134
26162
  policyStatus: policyResult.status,
26135
26163
  policy: policyResult.policy,
26136
26164
  effectivePreset: policyResult.policy?.enabled === true ? policyResult.policy.preset : "preserve",
26165
+ effectiveEmojiPolicy: "forbid-as-interface-icon",
26137
26166
  policyPath: relativePath(rootDir, designPolicyPath(rootDir)),
26138
- warning: policyResult.warning
26167
+ warning: effectivePolicyWarning(policyResult.policy, policyResult.warning)
26139
26168
  };
26140
26169
  return printResult(options.json, payload, [
26141
26170
  `Design policy: ${payload.policyStatus}`,
26142
26171
  `Effective preset: ${payload.effectivePreset}`,
26172
+ `Effective emoji policy: ${payload.effectiveEmojiPolicy}`,
26143
26173
  `Revision: ${payload.policy?.revision ?? 0}`,
26144
26174
  ...payload.warning === null ? [] : [`Warning: ${payload.warning}`]
26145
26175
  ]);
@@ -26162,7 +26192,7 @@ async function designContext(rootDir = process2.cwd(), options = {}) {
26162
26192
  ]);
26163
26193
  const configured = policyResult.policy;
26164
26194
  const active = configured?.enabled === true;
26165
- const policy = active ? configured : disabledPolicy();
26195
+ const policy = effectivePolicy(active ? configured : disabledPolicy());
26166
26196
  const rootUiDetected = profile?.uiAssets === "detected";
26167
26197
  const scopedUiDetected = style.scopeRoot !== "." && style.lastScanned !== null;
26168
26198
  const applicable = rootUiDetected || scopedUiDetected;
@@ -26185,10 +26215,16 @@ async function designContext(rootDir = process2.cwd(), options = {}) {
26185
26215
  doNotExpandTaskScope: true,
26186
26216
  reuseExistingDesignSystem: true,
26187
26217
  dependencyChangesRequireTaskApproval: true,
26188
- experimentalDoesNotAuthorizeProductChanges: true
26218
+ experimentalDoesNotAuthorizeProductChanges: true,
26219
+ interfaceEmojiIconsForbidden: true,
26220
+ contentEmojiAllowed: true,
26221
+ iconFallbackMustNotBeEmoji: true
26189
26222
  } : {
26190
26223
  doNotExpandTaskScope: true,
26191
- reuseExistingDesignSystem: true
26224
+ reuseExistingDesignSystem: true,
26225
+ interfaceEmojiIconsForbidden: true,
26226
+ contentEmojiAllowed: true,
26227
+ iconFallbackMustNotBeEmoji: true
26192
26228
  },
26193
26229
  project: {
26194
26230
  kind: profile?.projectKind ?? "unknown",
@@ -26198,7 +26234,7 @@ async function designContext(rootDir = process2.cwd(), options = {}) {
26198
26234
  guidance: designGuidance(policy),
26199
26235
  qualityGates: designQualityGates(policy),
26200
26236
  style,
26201
- warning: policyResult.warning
26237
+ warning: effectivePolicyWarning(configured, policyResult.warning)
26202
26238
  };
26203
26239
  return printResult(options.json, payload, [
26204
26240
  `Applicable: ${payload.applicable ? "yes" : "no"}`,
@@ -26237,6 +26273,7 @@ async function designConfigure(rootDir, options) {
26237
26273
  );
26238
26274
  }
26239
26275
  try {
26276
+ const legacyEmojiAllow = options.emoji === "allow";
26240
26277
  const result2 = await configureDesignPolicy({
26241
26278
  projectRoot: rootDir,
26242
26279
  expectedRevision,
@@ -26244,9 +26281,11 @@ async function designConfigure(rootDir, options) {
26244
26281
  confirmExperimental: options.confirmExperimental,
26245
26282
  ...values
26246
26283
  });
26247
- return printResult(options.json, { schemaVersion: 1, ...result2 }, [
26284
+ const warning = legacyEmojiAllow ? "--emoji allow is deprecated and was normalized to forbid-as-interface-icon; emoji remains allowed in user-authored content, chat messages, editorial copy, and domain data." : null;
26285
+ return printResult(options.json, { schemaVersion: 1, ...result2, warning }, [
26248
26286
  `Design policy configured: ${result2.policy.preset}`,
26249
- `Revision: ${result2.policy.revision}`
26287
+ `Revision: ${result2.policy.revision}`,
26288
+ ...warning === null ? [] : [`Warning: ${warning}`]
26250
26289
  ]);
26251
26290
  } catch (error) {
26252
26291
  const code = errorCode3(error, "MANCODE_DESIGN_CONFIGURE_FAILED");
@@ -26304,7 +26343,7 @@ function parseConfigureValues(options) {
26304
26343
  return {
26305
26344
  preset: options.preset,
26306
26345
  iconPolicy: options.icons,
26307
- emojiPolicy: options.emoji,
26346
+ emojiPolicy: options.emoji === "allow" ? "forbid-as-interface-icon" : options.emoji,
26308
26347
  motionPolicy: options.motion,
26309
26348
  browserValidation: options.browserValidation
26310
26349
  };
@@ -26389,22 +26428,28 @@ async function styleFreshness(rootDir, scopeRoot, lastScanned, sourceFiles) {
26389
26428
  function disabledPolicy() {
26390
26429
  return {
26391
26430
  ...DEFAULT_DESIGN_POLICY,
26392
- emojiPolicy: "allow",
26393
26431
  motionPolicy: "minimal",
26394
26432
  browserValidation: "off"
26395
26433
  };
26396
26434
  }
26435
+ function effectivePolicy(policy) {
26436
+ return policy.emojiPolicy === "forbid-as-interface-icon" ? policy : { ...policy, emojiPolicy: "forbid-as-interface-icon" };
26437
+ }
26438
+ function effectivePolicyWarning(policy, warning) {
26439
+ const legacyWarning = policy?.emojiPolicy === "allow" ? 'The legacy emoji policy "allow" is constrained to forbid-as-interface-icon; emoji remains allowed in user-authored content, chat messages, editorial copy, and domain data.' : null;
26440
+ return [warning, legacyWarning].filter(Boolean).join(" ") || null;
26441
+ }
26397
26442
  function designGuidance(policy) {
26398
26443
  return [
26399
26444
  directionSelectionGuidance(),
26400
26445
  presetGuidance(policy.preset),
26401
26446
  iconGuidance(policy.iconPolicy),
26402
- emojiGuidance(policy.emojiPolicy),
26447
+ emojiGuidance(),
26403
26448
  motionGuidance(policy.motionPolicy)
26404
26449
  ];
26405
26450
  }
26406
26451
  function directionSelectionGuidance() {
26407
- return "Before implementing a new UI surface or an aesthetic redesign when the user has not chosen a visual direction, present 2-3 distinct, product-appropriate directions with concise tradeoffs and a recommendation, then wait for the user to choose. Continue directly for scoped UI fixes or work within an established or already selected direction.";
26452
+ return VISUAL_DIRECTION_SELECTION_GUIDANCE;
26408
26453
  }
26409
26454
  function presetGuidance(preset) {
26410
26455
  if (preset === "refine") {
@@ -26418,8 +26463,8 @@ function presetGuidance(preset) {
26418
26463
  function iconGuidance(policy) {
26419
26464
  return policy === "lucide" ? "Use Lucide for interface icons when it is already available; adding or replacing a dependency requires explicit task approval." : "Reuse the project's existing icon system; do not introduce another icon library without explicit task approval.";
26420
26465
  }
26421
- function emojiGuidance(policy) {
26422
- return policy === "forbid-as-interface-icon" ? "Do not use emoji as interface icons." : "Follow the existing product conventions for emoji.";
26466
+ function emojiGuidance() {
26467
+ return INTERFACE_EMOJI_ICON_GUIDANCE.replace("Never use", "Do not use");
26423
26468
  }
26424
26469
  function motionGuidance(policy) {
26425
26470
  return policy === "purposeful" ? "Use motion only to clarify hierarchy, state changes, or spatial relationships, and preserve reduced-motion accessibility." : "Keep motion minimal and preserve reduced-motion accessibility.";
@@ -26429,6 +26474,7 @@ function designQualityGates(policy) {
26429
26474
  return [
26430
26475
  "Preserve task-critical workflows, keyboard access, visible focus, readable contrast, and responsive behavior on changed surfaces.",
26431
26476
  "Check changed surfaces for clipping, unintended overlap, horizontal overflow, and unstable layout.",
26477
+ "Inspect changed navigation, buttons, controls, actions, and status indicators to confirm that no emoji is used as an interface icon; do not flag emoji in user-authored content, chat messages, editorial copy, or domain data.",
26432
26478
  browserGate
26433
26479
  ];
26434
26480
  }
@@ -49174,7 +49220,10 @@ designProgram.command("context").description("Emit bounded UI design context for
49174
49220
  designProgram.command("configure").description("CAS-update the optional project design policy").requiredOption(
49175
49221
  "--expected-revision <n>",
49176
49222
  "Current policy revision; use 0 when absent"
49177
- ).option("--preset <preset>", "preserve, refine, or experimental").option("--icons <policy>", "existing-first or lucide").option("--emoji <policy>", "allow or forbid-as-interface-icon").option("--motion <policy>", "minimal or purposeful").option("--browser-validation <mode>", "off, when-available, or required").option("--confirm-experimental", "Explicitly allow the experimental preset").option("--json", "Output as JSON (for scripts)").action(async (options) => {
49223
+ ).option("--preset <preset>", "preserve, refine, or experimental").option("--icons <policy>", "existing-first or lucide").option(
49224
+ "--emoji <policy>",
49225
+ "forbid-as-interface-icon; legacy allow is normalized"
49226
+ ).option("--motion <policy>", "minimal or purposeful").option("--browser-validation <mode>", "off, when-available, or required").option("--confirm-experimental", "Explicitly allow the experimental preset").option("--json", "Output as JSON (for scripts)").action(async (options) => {
49178
49227
  process.exitCode = await designConfigure(process.cwd(), options);
49179
49228
  });
49180
49229
  designProgram.command("disable").description("Disable the project design policy without deleting it").requiredOption("--expected-revision <n>", "Current policy revision").option("--json", "Output as JSON (for scripts)").action(async (options) => {