@lokascript/compilation-service 2.9.4 → 2.10.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.
@@ -4219,6 +4219,37 @@ function parseTakeCommand(ctx, identifierNode) {
4219
4219
  }
4220
4220
  return CommandNodeBuilder.fromIdentifier(identifierNode).withArgs(...args).withModifiers(modifiers).endingAt(ctx.getPosition()).build();
4221
4221
  }
4222
+ function consumeViewTransitionTail(ctx, args) {
4223
+ if (!ctx.check("using")) {
4224
+ return false;
4225
+ }
4226
+ ctx.advance();
4227
+ if (!ctx.match("view")) {
4228
+ throw new Error("expected 'view transition' after 'using'");
4229
+ }
4230
+ if (!ctx.match("transition")) {
4231
+ throw new Error("expected 'transition' after 'using view'");
4232
+ }
4233
+ args.push(ctx.createIdentifier("using"));
4234
+ args.push(ctx.createIdentifier("view"));
4235
+ args.push(ctx.createIdentifier("transition"));
4236
+ return true;
4237
+ }
4238
+ function parseProcessCommand(ctx, identifierNode) {
4239
+ if (!ctx.check("partials")) {
4240
+ return null;
4241
+ }
4242
+ const args = [];
4243
+ consumeKeywordToArgs(ctx, "partials", args);
4244
+ if (consumeKeywordToArgs(ctx, KEYWORDS$1.IN, args)) {
4245
+ const contentArg = parseOneArgument(ctx, ["using"]);
4246
+ if (contentArg) {
4247
+ args.push(contentArg);
4248
+ }
4249
+ }
4250
+ consumeViewTransitionTail(ctx, args);
4251
+ return CommandNodeBuilder.fromIdentifier(identifierNode).withArgs(...args).endingAt(ctx.getPosition()).build();
4252
+ }
4222
4253
  function parseAddCommand(ctx, commandToken) {
4223
4254
  const args = [];
4224
4255
  if (ctx.match("{")) {
@@ -4326,6 +4357,7 @@ function parseSwapCommand(ctx, identifierNode) {
4326
4357
  args.push(contentExpr);
4327
4358
  }
4328
4359
  }
4360
+ consumeViewTransitionTail(ctx, args);
4329
4361
  return CommandNodeBuilder.fromIdentifier(identifierNode).withArgs(...args).endingAt(ctx.getPosition()).build();
4330
4362
  }
4331
4363
  function parseWaitCommand(ctx, commandToken) {
@@ -4789,6 +4821,8 @@ function parseCompoundCommand(ctx, identifierNode) {
4789
4821
  case "swap":
4790
4822
  case "morph":
4791
4823
  return parseSwapCommand(ctx, identifierNode);
4824
+ case "process":
4825
+ return parseProcessCommand(ctx, identifierNode) ?? parseRegularCommand(ctx, identifierNode);
4792
4826
  default:
4793
4827
  return parseRegularCommand(ctx, identifierNode);
4794
4828
  }
@@ -5101,6 +5135,9 @@ function parseTellCommand(ctx, identifierNode) {
5101
5135
  if (!target) {
5102
5136
  throw new Error("tell command requires a target expression");
5103
5137
  }
5138
+ if (ctx.check(KEYWORDS$1.TO)) {
5139
+ ctx.advance();
5140
+ }
5104
5141
  const commands = [];
5105
5142
  while (!ctx.isAtEnd()) {
5106
5143
  if (ctx.checkIsCommand()) {
@@ -5118,7 +5155,11 @@ function parseTellCommand(ctx, identifierNode) {
5118
5155
  if (ctx.match(KEYWORDS$1.AND) || ctx.match(KEYWORDS$1.THEN)) {
5119
5156
  continue;
5120
5157
  }
5121
- if (ctx.check(KEYWORDS$1.ELSE) || ctx.check(KEYWORDS$1.END)) {
5158
+ if (ctx.check(KEYWORDS$1.ELSE)) {
5159
+ break;
5160
+ }
5161
+ if (ctx.check(KEYWORDS$1.END)) {
5162
+ ctx.advance();
5122
5163
  break;
5123
5164
  }
5124
5165
  if (ctx.checkIsCommand()) {
@@ -7231,7 +7272,8 @@ var Parser = class _Parser {
7231
7272
  "closest",
7232
7273
  "js",
7233
7274
  "tell",
7234
- "fetch"
7275
+ "fetch",
7276
+ "process"
7235
7277
  ];
7236
7278
  if (this.semanticAdapter && !skipSemanticParsing.includes(commandName.toLowerCase())) {
7237
7279
  const remainingInput = this.getRemainingInput();
@@ -11196,7 +11238,7 @@ var CommandAdapterV2 = class {
11196
11238
  return {
11197
11239
  description: this.impl.metadata?.description || "",
11198
11240
  examples: this.impl.metadata?.examples || [],
11199
- syntax: Array.isArray(syntax) ? syntax.join(" | ") : syntax || ""
11241
+ syntax: typeof syntax === "string" ? syntax : syntax ? syntax.join(" | ") : ""
11200
11242
  };
11201
11243
  }
11202
11244
  async execute(context, ...args) {
@@ -11264,10 +11306,8 @@ var CommandAdapterV2 = class {
11264
11306
  }
11265
11307
  }
11266
11308
  validate(input) {
11267
- if (this.impl.validate) {
11268
- return this.impl.validate(input);
11269
- }
11270
- return { isValid: true, errors: [], suggestions: [] };
11309
+ const isValid = this.impl.validate ? this.impl.validate(input) : true;
11310
+ return { isValid, errors: [], suggestions: [] };
11271
11311
  }
11272
11312
  };
11273
11313
  var CommandRegistryV2 = class {
@@ -15928,7 +15968,7 @@ function command(config2) {
15928
15968
  };
15929
15969
  }
15930
15970
  function commandMeta(metadata) {
15931
- return { isBlocking: false, hasBody: false, version: "1.0.0", ...metadata };
15971
+ return { ...metadata };
15932
15972
  }
15933
15973
  function createFactory(CommandClass) {
15934
15974
  return () => new CommandClass();
@@ -19341,7 +19381,7 @@ var SwapCommand = (() => {
19341
19381
  };
19342
19382
  }
19343
19383
  }
19344
- let useViewTransition = false;
19384
+ let useViewTransition = raw.modifiers?.viewTransition !== void 0;
19345
19385
  if (usingIndex !== -1) {
19346
19386
  const afterUsing = argKeywords.slice(usingIndex + 1);
19347
19387
  if (afterUsing.includes("view") && afterUsing.includes("transition")) {
@@ -19537,7 +19577,7 @@ var MorphCommand = (() => {
19537
19577
  const withIndex = argKeywords.findIndex((k) => k === "with");
19538
19578
  const overIndex = argKeywords.findIndex((k) => k === "over");
19539
19579
  const usingIndex = argKeywords.findIndex((k) => k === "using");
19540
- let useViewTransition = false;
19580
+ let useViewTransition = raw.modifiers?.viewTransition !== void 0;
19541
19581
  if (usingIndex !== -1) {
19542
19582
  const afterUsing = argKeywords.slice(usingIndex + 1);
19543
19583
  if (afterUsing.includes("view") && afterUsing.includes("transition")) {
@@ -19613,7 +19653,11 @@ var MorphCommand = (() => {
19613
19653
  })();
19614
19654
  _classThis.metadata = commandMeta({
19615
19655
  description: "Morph content into target elements (intelligent diffing, preserves state)",
19616
- syntax: ["morph <target> with <content>", "morph over <target> with <content>"],
19656
+ syntax: [
19657
+ "morph <target> with <content>",
19658
+ "morph over <target> with <content>",
19659
+ "morph <target> with <content> using view transition"
19660
+ ],
19617
19661
  examples: ["morph #target with it", "morph over #modal with fetchedContent"],
19618
19662
  sideEffects: ["dom-mutation"],
19619
19663
  category: "dom",
@@ -20237,24 +20281,32 @@ var ProcessPartialsCommand = (() => {
20237
20281
  if (!args || args.length === 0) {
20238
20282
  throw new Error("process partials command requires content argument");
20239
20283
  }
20240
- const evaluatedArgs = [];
20241
- const argStrings = [];
20242
- for (const arg of args) {
20243
- const evaluated = await evaluator.evaluate(arg, context);
20244
- evaluatedArgs.push(evaluated);
20245
- if (typeof evaluated === "string") {
20246
- argStrings.push(evaluated.toLowerCase());
20247
- }
20248
- }
20249
- const partialsIndex = argStrings.findIndex((s) => s === "partials");
20284
+ const keywordOf = (node) => {
20285
+ const n = node;
20286
+ if (!n || typeof n !== "object")
20287
+ return null;
20288
+ if (n.type === "identifier" && typeof n.name === "string")
20289
+ return n.name.toLowerCase();
20290
+ if (n.type === "literal" && typeof n.value === "string")
20291
+ return n.value.toLowerCase();
20292
+ return null;
20293
+ };
20294
+ const keywords = args.map(keywordOf);
20295
+ const partialsIndex = keywords.indexOf("partials");
20296
+ const inIndex = keywords.indexOf("in");
20297
+ let contentNode;
20250
20298
  if (partialsIndex === -1) {
20251
- throw new Error('process command expects "partials" keyword: process partials in <content>');
20252
- }
20253
- const inIndex = argStrings.findIndex((s) => s === "in");
20254
- if (inIndex === -1 || inIndex <= partialsIndex) {
20255
- throw new Error('process partials command expects "in" keyword: process partials in <content>');
20299
+ if (inIndex !== -1) {
20300
+ throw new Error('process command expects "partials" keyword: process partials in <content>');
20301
+ }
20302
+ contentNode = args[0];
20303
+ } else {
20304
+ if (inIndex === -1 || inIndex <= partialsIndex) {
20305
+ throw new Error('process partials command expects "in" keyword: process partials in <content>');
20306
+ }
20307
+ contentNode = args[inIndex + 1];
20256
20308
  }
20257
- const contentArg = evaluatedArgs[inIndex + 1];
20309
+ const contentArg = contentNode ? await evaluator.evaluate(contentNode, context) : void 0;
20258
20310
  let html;
20259
20311
  if (typeof contentArg === "string") {
20260
20312
  html = contentArg;
@@ -20265,10 +20317,10 @@ var ProcessPartialsCommand = (() => {
20265
20317
  } else {
20266
20318
  throw new Error("process partials: content must be an HTML string or element");
20267
20319
  }
20268
- const usingIndex = argStrings.findIndex((s) => s === "using");
20269
- let useViewTransition = false;
20320
+ let useViewTransition = raw.modifiers?.viewTransition !== void 0;
20321
+ const usingIndex = keywords.indexOf("using");
20270
20322
  if (usingIndex !== -1) {
20271
- const remaining = argStrings.slice(usingIndex + 1).join(" ");
20323
+ const remaining = keywords.slice(usingIndex + 1);
20272
20324
  if (remaining.includes("view") && remaining.includes("transition")) {
20273
20325
  useViewTransition = true;
20274
20326
  }
@@ -34400,6 +34452,8 @@ var initSchema;
34400
34452
  var behaviorSchema;
34401
34453
  var installSchema;
34402
34454
  var measureSchema;
34455
+ var USING_VIEW_MARKER_ALL_LANGS;
34456
+ var VIEW_TRANSITION_MANNER_ROLE;
34403
34457
  var swapSchema;
34404
34458
  var morphSchema;
34405
34459
  var beepSchema;
@@ -34422,7 +34476,6 @@ var init_command_schemas = __esm({
34422
34476
  category: "dom-class",
34423
34477
  primaryRole: "patient",
34424
34478
  // `toggle .active on #btn for 2s` \u2192 args ['.active'], modifiers { on, for }.
34425
- // NOTE: `duration` is read here but not declared in `roles` below.
34426
34479
  ast: { args: ["patient"], modifiers: { on: "destination", for: "duration" } },
34427
34480
  roles: [
34428
34481
  {
@@ -35513,8 +35566,8 @@ var init_command_schemas = __esm({
35513
35566
  description: "Take content from a source element",
35514
35567
  category: "dom-content",
35515
35568
  primaryRole: "patient",
35516
- // `take .active from #parent` \u2192 args ['.active'], modifiers { from: '#parent' }.
35517
- ast: { args: ["patient"], modifiers: { from: "source" } },
35569
+ // `take .active from #parent for me` \u2192 args ['.active'], modifiers { from, for }.
35570
+ ast: { args: ["patient"], modifiers: { from: "source", for: "recipient" } },
35518
35571
  roles: [
35519
35572
  {
35520
35573
  role: "patient",
@@ -35537,6 +35590,38 @@ var init_command_schemas = __esm({
35537
35590
  expectedTypes: ["selector", "reference"],
35538
35591
  svoPosition: 2,
35539
35592
  sovPosition: 1
35593
+ },
35594
+ {
35595
+ role: "recipient",
35596
+ description: "The element the class moves ONTO (`take .active from .tab for me`)",
35597
+ required: false,
35598
+ // References only, deliberately. Upstream accepts an element expression,
35599
+ // but the 23 non-en corpus surfaces carry the recipient as a BARE
35600
+ // trailing pronoun (i18n renders `\u2026 von .tab-button ich`), so this slot
35601
+ // is marker-less almost everywhere and a selector-typed slot would
35602
+ // swallow the second selector of `take .active from .a .b`. English is
35603
+ // unaffected: `take` is on the core parser's skipSemanticParsing list,
35604
+ // so the traditional parser owns `for <anything>` there.
35605
+ expectedTypes: ["reference"],
35606
+ svoPosition: 3,
35607
+ sovPosition: 3,
35608
+ // NO default. The runtime already defaults the recipient to `me`
35609
+ // (commands/animation/take.ts), and a schema default would emit an
35610
+ // explicit `for me` modifier on every take \u2014 re-smuggling the exact
35611
+ // "absent means absent" semantics #859 removed from `source`.
35612
+ //
35613
+ // Shape-anchored on `reference`: without it this optional slot weighs
35614
+ // into every take pattern's denominator in `scoreRoleCoverage`, dropping
35615
+ // plain `take .active from .tab-button` from 1.0 to ~0.69 \u2014 the toggle-es
35616
+ // regression class the R1 role-set flip ratchet exists to catch.
35617
+ valueShape: "reference",
35618
+ // en only. The other 23 languages render the recipient unmarked, so a
35619
+ // marker there would never match their corpus rows; where the marker-less
35620
+ // slot proves inert they stay uncaptured and the pattern lands in the
35621
+ // baseline's `roleLossyPatterns` as named R1 burn-down tail. A language
35622
+ // gets a real particle here ONLY if the empty slot perturbs its other
35623
+ // parses (toggle's ja \u9593 / ko \ub3d9\uc548 case).
35624
+ markerOverride: { en: "for" }
35540
35625
  }
35541
35626
  ]
35542
35627
  };
@@ -36601,6 +36686,47 @@ var init_command_schemas = __esm({
36601
36686
  }
36602
36687
  ]
36603
36688
  };
36689
+ USING_VIEW_MARKER_ALL_LANGS = {
36690
+ en: "using view",
36691
+ es: "using view",
36692
+ pt: "using view",
36693
+ fr: "using view",
36694
+ de: "using view",
36695
+ it: "using view",
36696
+ ja: "using view",
36697
+ ko: "using view",
36698
+ zh: "using view",
36699
+ ar: "using view",
36700
+ he: "using view",
36701
+ hi: "using view",
36702
+ bn: "using view",
36703
+ tr: "using view",
36704
+ ru: "using view",
36705
+ uk: "using view",
36706
+ pl: "using view",
36707
+ id: "using view",
36708
+ vi: "using view",
36709
+ th: "using view",
36710
+ ms: "using view",
36711
+ tl: "using view",
36712
+ sw: "using view",
36713
+ qu: "using view"
36714
+ };
36715
+ VIEW_TRANSITION_MANNER_ROLE = {
36716
+ role: "manner",
36717
+ description: "Run the swap inside a `document.startViewTransition()` (`using view transition`)",
36718
+ required: false,
36719
+ // Both types, because the SAME word tokenizes differently per language and
36720
+ // the difference is an accident of vocabulary: `transition` is a command
36721
+ // keyword in en/fr (it is also their verb) and a bare identifier everywhere
36722
+ // else, which types it `literal` in the first group and `expression` in the
36723
+ // second. Measured: with `['literal']` alone only en and fr captured the
36724
+ // tail. Widening is safe precisely because the slot is marker-guarded \u2014
36725
+ // nothing reaches it until `using view` has matched.
36726
+ expectedTypes: ["literal", "expression"],
36727
+ valueShape: "keyword",
36728
+ markerOverride: USING_VIEW_MARKER_ALL_LANGS
36729
+ };
36604
36730
  swapSchema = {
36605
36731
  action: "swap",
36606
36732
  description: "Swap DOM content using various strategies (innerHTML, outerHTML, delete, etc.)",
@@ -36621,7 +36747,11 @@ var init_command_schemas = __esm({
36621
36747
  // work. Preserved verbatim by the Arc F migration (a faithful migration must
36622
36748
  // not change output) and pinned as two `drift` exemptions; this is the
36623
36749
  // behavior fix those entries were waiting for.
36624
- ast: { args: ["method", "destination", "patient"] },
36750
+ //
36751
+ // `manner` is the exception to "keyword-positional args": it rides as
36752
+ // `modifiers.viewTransition`, which SwapCommand.parseInput reads for presence
36753
+ // alongside its existing flat-args `using`/`view`/`transition` scan.
36754
+ ast: { args: ["method", "destination", "patient"], modifiers: { viewTransition: "manner" } },
36625
36755
  roles: [
36626
36756
  {
36627
36757
  role: "method",
@@ -36716,6 +36846,11 @@ var init_command_schemas = __esm({
36716
36846
  ar: "\u0628\u0640",
36717
36847
  tl: "nang"
36718
36848
  }
36849
+ },
36850
+ {
36851
+ ...VIEW_TRANSITION_MANNER_ROLE,
36852
+ svoPosition: 4,
36853
+ sovPosition: 4
36719
36854
  }
36720
36855
  ]
36721
36856
  };
@@ -36726,7 +36861,15 @@ var init_command_schemas = __esm({
36726
36861
  primaryRole: "patient",
36727
36862
  // `morph #list to it` \u2192 args [content], modifiers { on: element }.
36728
36863
  // Content is source or destination; the element being morphed is the patient.
36729
- ast: { args: [["source", "destination"]], modifiers: { on: "patient" } },
36864
+ //
36865
+ // `manner` rides as `modifiers.viewTransition`, same as swap/process \u2014
36866
+ // MorphCommand.parseInput reads it for presence alongside its existing
36867
+ // flat-args `using`/`view`/`transition` scan (the traditional-parser path,
36868
+ // which owns English because morph sits on SKIP_SEMANTIC_COMMANDS).
36869
+ ast: {
36870
+ args: [["source", "destination"]],
36871
+ modifiers: { on: "patient", viewTransition: "manner" }
36872
+ },
36730
36873
  roles: [
36731
36874
  {
36732
36875
  role: "patient",
@@ -36747,6 +36890,18 @@ var init_command_schemas = __esm({
36747
36890
  sovPosition: 2,
36748
36891
  markerOverride: { en: "to" }
36749
36892
  // "morph #target to it"
36893
+ },
36894
+ {
36895
+ // `morph #target to it using view transition` \u2014 the same tail as swap and
36896
+ // process, closed here for the same reason (#870's third-schema filing):
36897
+ // without the role the semantic parser matched morph at confidence 1.0
36898
+ // and stranded the tail, so every semantic-only consumer (multilingual
36899
+ // bundles, the bridge, `translate()`) silently dropped the animation
36900
+ // request in all 24 languages. Morph has NO hand-written patterns in any
36901
+ // language, so this schema role is the whole fix on the pattern side.
36902
+ ...VIEW_TRANSITION_MANNER_ROLE,
36903
+ svoPosition: 3,
36904
+ sovPosition: 3
36750
36905
  }
36751
36906
  ]
36752
36907
  };
@@ -36933,6 +37088,13 @@ var init_command_schemas = __esm({
36933
37088
  description: "Process hx-partial markup in HTML content",
36934
37089
  category: "dom-content",
36935
37090
  primaryRole: "patient",
37091
+ // `process partials in it` \u2192 args ['it']; the optional tail rides as
37092
+ // `modifiers.viewTransition`, which ProcessPartialsCommand.parseInput has
37093
+ // read since #861 (`raw.modifiers?.viewTransition !== undefined`). Without a
37094
+ // descriptor this schema fell through to `buildGenericCommand`, whose
37095
+ // modifier list is fixed (destination/duration/method/style) and would have
37096
+ // dropped a captured `manner` on the floor.
37097
+ ast: { args: ["patient"], modifiers: { viewTransition: "manner" } },
36936
37098
  roles: [
36937
37099
  {
36938
37100
  role: "patient",
@@ -36942,6 +37104,11 @@ var init_command_schemas = __esm({
36942
37104
  svoPosition: 1,
36943
37105
  sovPosition: 1,
36944
37106
  markerOverride: PARTIALS_IN_MARKER_ALL_LANGS
37107
+ },
37108
+ {
37109
+ ...VIEW_TRANSITION_MANNER_ROLE,
37110
+ svoPosition: 2,
37111
+ sovPosition: 2
36945
37112
  }
36946
37113
  ]
36947
37114
  };
@@ -38526,7 +38693,9 @@ var init_french = __esm({
38526
38693
  trigger: { primary: "d\xE9clencher", normalized: "trigger" },
38527
38694
  send: { primary: "envoyer", alternatives: ["envoie"], normalized: "send" },
38528
38695
  focus: { primary: "focaliser", alternatives: ["concentrer"], normalized: "focus" },
38529
- blur: { primary: "d\xE9focaliser", normalized: "blur" },
38696
+ // `d\u00e9focaliser` is an unattested infinitive; French pedagogy writes
38697
+ // `perte de focus` for the event (2026-07 terminology review).
38698
+ blur: { primary: "perte de focus", alternatives: ["d\xE9focaliser"], normalized: "blur" },
38530
38699
  // Phase 1 (v0.9.90): DOM / form state / debug
38531
38700
  // `vide` (adjective, "empty") is the i18n transformer's `is empty` predicate
38532
38701
  // form; `vider` is the verb ("to empty"). Accept both so the emptiness check
@@ -38539,7 +38708,13 @@ var init_french = __esm({
38539
38708
  reset: { primary: "r\xE9initialiser", alternatives: ["reinitialiser"], normalized: "reset" },
38540
38709
  breakpoint: { primary: "point-arr\xEAt", alternatives: ["point-arret"], normalized: "breakpoint" },
38541
38710
  go: { primary: "aller", alternatives: ["naviguer", "va"], normalized: "go" },
38542
- scroll: { primary: "d\xE9filer", alternatives: ["faire-d\xE9filer"], normalized: "scroll" },
38711
+ // MDN fr and the OQLF standardize the noun `d\u00e9filement` for the event; the
38712
+ // infinitive stays as an alternative.
38713
+ scroll: {
38714
+ primary: "d\xE9filement",
38715
+ alternatives: ["defilement", "d\xE9filer", "faire-d\xE9filer"],
38716
+ normalized: "scroll"
38717
+ },
38543
38718
  push: { primary: "pousser", normalized: "push" },
38544
38719
  replace: { primary: "remplacer", normalized: "replace" },
38545
38720
  process: { primary: "traiter", normalized: "process" },
@@ -38605,9 +38780,15 @@ var init_french = __esm({
38605
38780
  after: { primary: "apr\xE8s", normalized: "after" },
38606
38781
  // Common event names (for event handler patterns)
38607
38782
  click: { primary: "clic", alternatives: ["clique"], normalized: "click" },
38608
- // `resize` event (window-resize): dict emits redimensionner; register it so the
38609
- // event types as literal="resize" (matching en) instead of expression.
38610
- resize: { primary: "redimensionner", normalized: "resize" },
38783
+ // `resize` event (window-resize): the noun `redimensionnement` is the
38784
+ // attested event form ("lors du redimensionnement de la fen\u00eatre"). The dict
38785
+ // still emits redimensionner, kept as an alternative so the event keeps
38786
+ // typing as literal="resize" (matching en) instead of expression.
38787
+ resize: {
38788
+ primary: "redimensionnement",
38789
+ alternatives: ["redimensionner"],
38790
+ normalized: "resize"
38791
+ },
38611
38792
  hover: { primary: "survol", alternatives: ["survoler"], normalized: "hover" },
38612
38793
  submit: { primary: "soumission", alternatives: ["soumettre"], normalized: "submit" },
38613
38794
  input: { primary: "saisie", alternatives: ["entr\xE9e"], normalized: "input" },
@@ -42360,9 +42541,17 @@ var init_turkish = __esm({
42360
42541
  on: { primary: "\xFCzerinde", alternatives: ["zaman"], normalized: "on" },
42361
42542
  trigger: { primary: "tetikle", normalized: "trigger" },
42362
42543
  send: { primary: "g\xF6nder", normalized: "send" },
42363
- // DOM focus
42364
- focus: { primary: "odak", alternatives: ["odaklanma"], normalized: "focus" },
42365
- blur: { primary: "bulan\u0131k", alternatives: ["bulan\u0131kl\u0131k", "bulanik"], normalized: "blur" },
42544
+ // DOM focus. `odaklanma` (the act of focusing) leads over the static state
42545
+ // noun `odak` \u2014 Turkish event prose says "odaklanma olay\u0131". `bulan\u0131k` was
42546
+ // the optical blur (CSS filters, image processing), never the DOM event;
42547
+ // native usage is `odak kayb\u0131` (loss of focus). 2026-07 terminology-review
42548
+ // corrections; old forms stay as parse alternatives.
42549
+ focus: { primary: "odaklanma", alternatives: ["odak"], normalized: "focus" },
42550
+ blur: {
42551
+ primary: "odak kayb\u0131",
42552
+ alternatives: ["odak kaybi", "bulan\u0131k", "bulan\u0131kl\u0131k", "bulanik"],
42553
+ normalized: "blur"
42554
+ },
42366
42555
  // Phase 1 (v0.9.90): DOM / form state / debug
42367
42556
  empty: { primary: "bo\u015Falt", alternatives: ["bosalt", "bo\u015F"], normalized: "empty" },
42368
42557
  open: { primary: "a\xE7", alternatives: ["ac"], normalized: "open" },
@@ -42383,7 +42572,9 @@ var init_turkish = __esm({
42383
42572
  },
42384
42573
  hover: { primary: "\xFCzerine gelme", alternatives: ["\xFCzerinde gezinme"], normalized: "hover" },
42385
42574
  submit: { primary: "g\xF6nderme", normalized: "submit" },
42386
- input: { primary: "giri\u015F", alternatives: ["girdi", "giris"], normalized: "input" },
42575
+ // `giri\u015f` reads as entry/login (giri\u015f yapma) and can imply an auth event;
42576
+ // the data-input term is `girdi` ("Girdi (Input) Eventleri").
42577
+ input: { primary: "girdi", alternatives: ["giri\u015F", "giris"], normalized: "input" },
42387
42578
  change: { primary: "de\u011Fi\u015Fiklik", alternatives: ["de\u011Fi\u015Fim", "degisim"], normalized: "change" },
42388
42579
  // `load` event: the i18n dict emits y\u00fckle for `load`. Without this keyword the
42389
42580
  // SOV reorder's mid-stream `y\u00fckle de` (on load) tokenized as the `install`
@@ -42393,7 +42584,13 @@ var init_turkish = __esm({
42393
42584
  load: { primary: "y\xFCkle", normalized: "load" },
42394
42585
  // Navigation
42395
42586
  go: { primary: "git", normalized: "go" },
42396
- scroll: { primary: "kayd\u0131r", alternatives: ["kaydir"], normalized: "scroll" },
42587
+ // `kayd\u0131r` is the bare imperative; the attested event noun is `kayd\u0131rma`
42588
+ // ("kayd\u0131rma olay\u0131"). The imperative stays as an alternative.
42589
+ scroll: {
42590
+ primary: "kayd\u0131rma",
42591
+ alternatives: ["kaydirma", "kayd\u0131r", "kaydir"],
42592
+ normalized: "scroll"
42593
+ },
42397
42594
  push: { primary: "itele", alternatives: ["push"], normalized: "push" },
42398
42595
  replace: { primary: "de\u011Fi\u015Ftir_url", alternatives: ["degistir_url"], normalized: "replace" },
42399
42596
  process: { primary: "i\u015Fle", alternatives: ["isle"], normalized: "process" },
@@ -43339,6 +43536,58 @@ var init_chinese = __esm({
43339
43536
  };
43340
43537
  }
43341
43538
  });
43539
+ function resolveMarkerForRole(roleSpec, profile) {
43540
+ const overrideMarker = roleSpec.markerOverride?.[profile.code];
43541
+ const defaultMarker = profile.roleMarkers[roleSpec.role];
43542
+ if (overrideMarker !== void 0) {
43543
+ const alternatives = legacyMarkerAlternatives(roleSpec, profile.code, overrideMarker);
43544
+ return {
43545
+ primary: overrideMarker,
43546
+ ...alternatives && { alternatives },
43547
+ position: defaultMarker?.position ?? "before",
43548
+ isOverride: true
43549
+ };
43550
+ }
43551
+ if (defaultMarker && defaultMarker.primary) {
43552
+ const result = {
43553
+ primary: defaultMarker.primary,
43554
+ position: defaultMarker.position,
43555
+ isOverride: false
43556
+ };
43557
+ if (defaultMarker.alternatives) {
43558
+ result.alternatives = defaultMarker.alternatives;
43559
+ }
43560
+ return result;
43561
+ }
43562
+ return null;
43563
+ }
43564
+ function legacyMarkerAlternatives(roleSpec, languageCode, overrideMarker) {
43565
+ const legacy = roleSpec.markerLegacy?.[languageCode];
43566
+ if (!legacy?.length) return void 0;
43567
+ const alternatives = [...new Set(legacy)].filter((a) => a && a !== overrideMarker);
43568
+ return alternatives.length ? alternatives : void 0;
43569
+ }
43570
+ function schemaMarkerAlternatives(roleSpec, languageCode, marker) {
43571
+ const legacy = roleSpec.markerLegacy?.[languageCode] ?? [];
43572
+ const variants = roleSpec.methodCarrier ? [] : roleSpec.markerVariants?.[languageCode] ?? [];
43573
+ const alternatives = [.../* @__PURE__ */ new Set([...legacy, ...variants])].filter((a) => a && a !== marker);
43574
+ return alternatives.length ? alternatives : void 0;
43575
+ }
43576
+ var ROLE_MARKER_CONCEPTS;
43577
+ var init_marker_resolution = __esm({
43578
+ "src/parser/utils/marker-resolution.ts"() {
43579
+ ROLE_MARKER_CONCEPTS = /* @__PURE__ */ new Set([
43580
+ "destination",
43581
+ "source",
43582
+ "patient",
43583
+ "object",
43584
+ "event",
43585
+ "eventmarker",
43586
+ "manner",
43587
+ "instrument"
43588
+ ]);
43589
+ }
43590
+ });
43342
43591
  function getPutPatternsBn() {
43343
43592
  return [
43344
43593
  // SOV verb-final positional put: `{patient} <posWord> {destination} \u0995\u09c7 \u09b0\u09be\u0996\u09c1\u09a8`
@@ -58214,47 +58463,6 @@ var init_role_positioning = __esm({
58214
58463
  "src/parser/utils/role-positioning.ts"() {
58215
58464
  }
58216
58465
  });
58217
- function resolveMarkerForRole(roleSpec, profile) {
58218
- const overrideMarker = roleSpec.markerOverride?.[profile.code];
58219
- const defaultMarker = profile.roleMarkers[roleSpec.role];
58220
- if (overrideMarker !== void 0) {
58221
- const alternatives = legacyMarkerAlternatives(roleSpec, profile.code, overrideMarker);
58222
- return {
58223
- primary: overrideMarker,
58224
- ...alternatives && { alternatives },
58225
- position: defaultMarker?.position ?? "before",
58226
- isOverride: true
58227
- };
58228
- }
58229
- if (defaultMarker && defaultMarker.primary) {
58230
- const result = {
58231
- primary: defaultMarker.primary,
58232
- position: defaultMarker.position,
58233
- isOverride: false
58234
- };
58235
- if (defaultMarker.alternatives) {
58236
- result.alternatives = defaultMarker.alternatives;
58237
- }
58238
- return result;
58239
- }
58240
- return null;
58241
- }
58242
- function legacyMarkerAlternatives(roleSpec, languageCode, overrideMarker) {
58243
- const legacy = roleSpec.markerLegacy?.[languageCode];
58244
- if (!legacy?.length) return void 0;
58245
- const alternatives = [...new Set(legacy)].filter((a) => a && a !== overrideMarker);
58246
- return alternatives.length ? alternatives : void 0;
58247
- }
58248
- function schemaMarkerAlternatives(roleSpec, languageCode, marker) {
58249
- const legacy = roleSpec.markerLegacy?.[languageCode] ?? [];
58250
- const variants = roleSpec.methodCarrier ? [] : roleSpec.markerVariants?.[languageCode] ?? [];
58251
- const alternatives = [.../* @__PURE__ */ new Set([...legacy, ...variants])].filter((a) => a && a !== marker);
58252
- return alternatives.length ? alternatives : void 0;
58253
- }
58254
- var init_marker_resolution = __esm({
58255
- "src/parser/utils/marker-resolution.ts"() {
58256
- }
58257
- });
58258
58466
  function resolveRoleMarker(roleSpec, profile) {
58259
58467
  let marker;
58260
58468
  let alternatives;
@@ -58287,6 +58495,43 @@ function appendOptionalScope(tokens, extraction, commandSchema) {
58287
58495
  });
58288
58496
  extraction.scope = { fromRole: "scope" };
58289
58497
  }
58498
+ function appendOptionalViewTransition(tokens, extraction, commandSchema, languageCode) {
58499
+ appendOptionalTailRole(tokens, extraction, commandSchema, languageCode, "manner", {
58500
+ requireMarker: true
58501
+ });
58502
+ }
58503
+ function appendOptionalRecipient(tokens, extraction, commandSchema, languageCode) {
58504
+ appendOptionalTailRole(tokens, extraction, commandSchema, languageCode, "recipient", {
58505
+ requireMarker: false
58506
+ });
58507
+ }
58508
+ function appendOptionalTailRole(tokens, extraction, commandSchema, languageCode, role, opts) {
58509
+ const spec = commandSchema.roles.find((r) => r.role === role && !r.required);
58510
+ if (!spec) return;
58511
+ const marker = spec.markerOverride?.[languageCode];
58512
+ if (opts.requireMarker && !marker) return;
58513
+ tokens.push({
58514
+ type: "group",
58515
+ optional: true,
58516
+ tokens: [
58517
+ ...(marker ? marker.split(/\s+/) : []).map(
58518
+ (word) => ({ type: "literal", value: word })
58519
+ ),
58520
+ {
58521
+ type: "role",
58522
+ role,
58523
+ optional: true,
58524
+ expectedTypes: spec.expectedTypes,
58525
+ // Load-bearing, same as on the generated command patterns: it exempts
58526
+ // the trailing slot from the matcher's verb guard, keeps the uncaptured
58527
+ // slot out of `scoreRoleCoverage`'s denominator, and (for `keyword`)
58528
+ // normalizes the captured value type to the EN reference's `literal`.
58529
+ ...spec.valueShape !== void 0 ? { valueShape: spec.valueShape } : {}
58530
+ }
58531
+ ]
58532
+ });
58533
+ extraction[role] = { fromRole: role };
58534
+ }
58290
58535
  function generateSOVEventHandlerPattern(commandSchema, profile, keyword, eventMarker, config2) {
58291
58536
  const tokens = [];
58292
58537
  tokens.push({ type: "role", role: "event", optional: false });
@@ -58381,6 +58626,15 @@ function generateSOVPatientFirstEventHandlerPattern(commandSchema, profile, keyw
58381
58626
  tokens.push(
58382
58627
  ...swapsOperands ? eventHandlerPatientGroup(commandSchema, trailingMarker) : eventHandlerDestinationGroup(commandSchema, trailingMarker)
58383
58628
  );
58629
+ const extraction = {
58630
+ action: { value: commandSchema.action },
58631
+ event: { fromRole: "event" },
58632
+ [frontedRole]: { fromRole: frontedRole },
58633
+ ...swapsOperands ? {} : eventHandlerDestinationExtraction(commandSchema),
58634
+ ...eventHandlerSourceExtraction(commandSchema)
58635
+ };
58636
+ appendOptionalRecipient(tokens, extraction, commandSchema, profile.code);
58637
+ appendOptionalViewTransition(tokens, extraction, commandSchema, profile.code);
58384
58638
  return {
58385
58639
  id: `${commandSchema.action}-event-${profile.code}-sov-patient-first`,
58386
58640
  language: profile.code,
@@ -58390,13 +58644,7 @@ function generateSOVPatientFirstEventHandlerPattern(commandSchema, profile, keyw
58390
58644
  format: `{patient} ${patientMarker?.primary || ""} {event} ${eventMarker.primary} ${keyword.primary}`,
58391
58645
  tokens
58392
58646
  },
58393
- extraction: {
58394
- action: { value: commandSchema.action },
58395
- event: { fromRole: "event" },
58396
- [frontedRole]: { fromRole: frontedRole },
58397
- ...swapsOperands ? {} : eventHandlerDestinationExtraction(commandSchema),
58398
- ...eventHandlerSourceExtraction(commandSchema)
58399
- }
58647
+ extraction
58400
58648
  };
58401
58649
  }
58402
58650
  function generateSOVPatientFirstWithDestEventHandlerPattern(commandSchema, profile, keyword, eventMarker, config2) {
@@ -58836,6 +59084,16 @@ function generateVSOVerbFirstEventHandlerPattern(commandSchema, profile, keyword
58836
59084
  });
58837
59085
  }
58838
59086
  }
59087
+ const extraction = {
59088
+ action: { value: commandSchema.action },
59089
+ event: { fromRole: "event" },
59090
+ [swapsOperands ? "destination" : "patient"]: {
59091
+ fromRole: swapsOperands ? "destination" : "patient"
59092
+ },
59093
+ ...swapsOperands ? {} : eventHandlerDestinationExtraction(commandSchema),
59094
+ ...eventHandlerSourceExtraction(commandSchema)
59095
+ };
59096
+ appendOptionalViewTransition(tokens, extraction, commandSchema, profile.code);
58839
59097
  return {
58840
59098
  id: `${commandSchema.action}-event-${profile.code}-vso-verb-first`,
58841
59099
  language: profile.code,
@@ -58846,15 +59104,7 @@ function generateVSOVerbFirstEventHandlerPattern(commandSchema, profile, keyword
58846
59104
  format: `${keyword.primary} {patient} ${destMarker?.primary || ""} {destination?} ${eventMarker.primary} {event}`,
58847
59105
  tokens
58848
59106
  },
58849
- extraction: {
58850
- action: { value: commandSchema.action },
58851
- event: { fromRole: "event" },
58852
- [swapsOperands ? "destination" : "patient"]: {
58853
- fromRole: swapsOperands ? "destination" : "patient"
58854
- },
58855
- ...swapsOperands ? {} : eventHandlerDestinationExtraction(commandSchema),
58856
- ...eventHandlerSourceExtraction(commandSchema)
58857
- }
59107
+ extraction
58858
59108
  };
58859
59109
  }
58860
59110
  function generateVSOVerbFirstTwoRoleEventHandlerPattern(commandSchema, profile, keyword, eventMarker, config2) {
@@ -59454,7 +59704,11 @@ function buildRoleToken(roleSpec, profile) {
59454
59704
  type: "role",
59455
59705
  role: roleSpec.role,
59456
59706
  optional: !roleSpec.required,
59457
- expectedTypes: roleSpec.expectedTypes
59707
+ expectedTypes: roleSpec.expectedTypes,
59708
+ // The matcher reads this too \u2014 a `'keyword'`-shaped slot holds a fixed
59709
+ // keyword phrase (`using view transition`) and must not be skipped by the
59710
+ // trailing-slot verb guard.
59711
+ ...roleSpec.valueShape !== void 0 ? { valueShape: roleSpec.valueShape } : {}
59458
59712
  };
59459
59713
  const prefixLiteral = roleSpec.valuePrefixLiteral?.[profile.code];
59460
59714
  const pushPrefixed = () => {
@@ -59762,6 +60016,7 @@ var init_pick = __esm({
59762
60016
  pickPatternsEn = [pickVariantEnglish];
59763
60017
  }
59764
60018
  });
60019
+ var VIEW_TRANSITION_TAIL;
59765
60020
  var swapSimpleEnglish;
59766
60021
  var swapElementEnglish;
59767
60022
  var swapStrategyOfEnglish;
@@ -59769,6 +60024,21 @@ var swapStrategyEnglish;
59769
60024
  var swapPatternsEn;
59770
60025
  var init_swap = __esm({
59771
60026
  "src/patterns/languages/en/swap.ts"() {
60027
+ VIEW_TRANSITION_TAIL = {
60028
+ type: "group",
60029
+ optional: true,
60030
+ tokens: [
60031
+ { type: "literal", value: "using" },
60032
+ { type: "literal", value: "view" },
60033
+ {
60034
+ type: "role",
60035
+ role: "manner",
60036
+ optional: true,
60037
+ expectedTypes: ["literal", "expression"],
60038
+ valueShape: "keyword"
60039
+ }
60040
+ ]
60041
+ };
59772
60042
  swapSimpleEnglish = {
59773
60043
  id: "swap-en-handcrafted",
59774
60044
  language: "en",
@@ -59776,11 +60046,12 @@ var init_swap = __esm({
59776
60046
  priority: 110,
59777
60047
  // Higher than generated patterns
59778
60048
  template: {
59779
- format: "swap {method} {destination}",
60049
+ format: "swap {method} {destination} [using view {manner}]",
59780
60050
  tokens: [
59781
60051
  { type: "literal", value: "swap" },
59782
60052
  { type: "role", role: "method" },
59783
- { type: "role", role: "destination" }
60053
+ { type: "role", role: "destination" },
60054
+ VIEW_TRANSITION_TAIL
59784
60055
  ]
59785
60056
  },
59786
60057
  extraction: {
@@ -59794,12 +60065,13 @@ var init_swap = __esm({
59794
60065
  command: "swap",
59795
60066
  priority: 120,
59796
60067
  template: {
59797
- format: "swap {destination} with {patient}",
60068
+ format: "swap {destination} with {patient} [using view {manner}]",
59798
60069
  tokens: [
59799
60070
  { type: "literal", value: "swap" },
59800
60071
  { type: "role", role: "destination" },
59801
60072
  { type: "literal", value: "with" },
59802
- { type: "role", role: "patient" }
60073
+ { type: "role", role: "patient" },
60074
+ VIEW_TRANSITION_TAIL
59803
60075
  ]
59804
60076
  },
59805
60077
  extraction: {}
@@ -59810,14 +60082,15 @@ var init_swap = __esm({
59810
60082
  command: "swap",
59811
60083
  priority: 140,
59812
60084
  template: {
59813
- format: "swap {method} of {destination} with {patient}",
60085
+ format: "swap {method} of {destination} with {patient} [using view {manner}]",
59814
60086
  tokens: [
59815
60087
  { type: "literal", value: "swap" },
59816
60088
  { type: "role", role: "method" },
59817
60089
  { type: "literal", value: "of" },
59818
60090
  { type: "role", role: "destination" },
59819
60091
  { type: "literal", value: "with" },
59820
- { type: "role", role: "patient" }
60092
+ { type: "role", role: "patient" },
60093
+ VIEW_TRANSITION_TAIL
59821
60094
  ]
59822
60095
  },
59823
60096
  extraction: {}
@@ -59828,13 +60101,14 @@ var init_swap = __esm({
59828
60101
  command: "swap",
59829
60102
  priority: 130,
59830
60103
  template: {
59831
- format: "swap {method} {destination} with {patient}",
60104
+ format: "swap {method} {destination} with {patient} [using view {manner}]",
59832
60105
  tokens: [
59833
60106
  { type: "literal", value: "swap" },
59834
60107
  { type: "role", role: "method" },
59835
60108
  { type: "role", role: "destination" },
59836
60109
  { type: "literal", value: "with" },
59837
- { type: "role", role: "patient" }
60110
+ { type: "role", role: "patient" },
60111
+ VIEW_TRANSITION_TAIL
59838
60112
  ]
59839
60113
  },
59840
60114
  extraction: {}
@@ -63325,6 +63599,7 @@ function isTypeCompatible(actualType, expectedTypes) {
63325
63599
  }
63326
63600
  return false;
63327
63601
  }
63602
+ init_marker_resolution();
63328
63603
  init_command_schemas();
63329
63604
  init_english();
63330
63605
  function getPossessiveReference(profile, keyword) {
@@ -63877,7 +64152,8 @@ var DefaultConfidenceModel = class {
63877
64152
  const hasDefault = (role) => {
63878
64153
  return pattern.extraction?.[role]?.default !== void 0;
63879
64154
  };
63880
- const schemaRoles = commandSchemas[pattern.command]?.roles;
64155
+ const wrappedAction = pattern.command === "on" ? pattern.extraction?.action?.value : void 0;
64156
+ const schemaRoles = commandSchemas[wrappedAction ?? pattern.command]?.roles;
63881
64157
  const isShapeAnchored = (role) => schemaRoles?.find((r) => r.role === role)?.valueShape !== void 0;
63882
64158
  for (const token of pattern.template.tokens) {
63883
64159
  if (token.type === "role") {
@@ -64270,7 +64546,7 @@ var _PatternMatcher2 = class _PatternMatcher3 {
64270
64546
  return patternToken.optional || false;
64271
64547
  }
64272
64548
  }
64273
- if (patternToken.optional && nextPatternToken === void 0 && patternToken.role !== "event" && patternToken.role !== "action" && token.kind === "keyword") {
64549
+ if (patternToken.optional && nextPatternToken === void 0 && patternToken.role !== "event" && patternToken.role !== "action" && patternToken.valueShape !== "keyword" && token.kind === "keyword") {
64274
64550
  const verbNorm = (token.normalized ?? token.value).toLowerCase();
64275
64551
  if (verbNorm in commandSchemas) {
64276
64552
  return true;
@@ -64425,7 +64701,11 @@ var _PatternMatcher2 = class _PatternMatcher3 {
64425
64701
  }
64426
64702
  }
64427
64703
  }
64428
- captured.set(patternToken.role, value);
64704
+ if (patternToken.valueShape === "keyword" && value.type === "expression") {
64705
+ captured.set(patternToken.role, createLiteral(String(value.raw ?? "")));
64706
+ } else {
64707
+ captured.set(patternToken.role, value);
64708
+ }
64429
64709
  tokens.advance();
64430
64710
  if (patternToken.role === "event") {
64431
64711
  const filterTok = tokens.peek();
@@ -65014,17 +65294,7 @@ var _PatternMatcher2 = class _PatternMatcher3 {
65014
65294
  * so this never blocks a genuine `my value` / `its style` possessive.
65015
65295
  */
65016
65296
  isRoleMarkerConcept(normalized2) {
65017
- const markerConcepts = /* @__PURE__ */ new Set([
65018
- "destination",
65019
- "source",
65020
- "patient",
65021
- "object",
65022
- "event",
65023
- "eventmarker",
65024
- "manner",
65025
- "instrument"
65026
- ]);
65027
- return markerConcepts.has(normalized2.toLowerCase());
65297
+ return ROLE_MARKER_CONCEPTS.has(normalized2.toLowerCase());
65028
65298
  }
65029
65299
  /**
65030
65300
  * Does `token` look like an EVENT name for the `event` role? Events are bare
@@ -65410,7 +65680,7 @@ var _PatternMatcher2 = class _PatternMatcher3 {
65410
65680
  */
65411
65681
  matchGroupToken(tokens, patternToken, captured, nextPatternToken) {
65412
65682
  const mark = tokens.mark();
65413
- const capturedBefore = new Set(captured.keys());
65683
+ const capturedBefore = new Map(captured);
65414
65684
  const success = this.matchTokenSequence(
65415
65685
  tokens,
65416
65686
  patternToken.tokens,
@@ -65424,6 +65694,11 @@ var _PatternMatcher2 = class _PatternMatcher3 {
65424
65694
  captured.delete(role);
65425
65695
  }
65426
65696
  }
65697
+ for (const [role, value] of capturedBefore) {
65698
+ if (captured.get(role) !== value) {
65699
+ captured.set(role, value);
65700
+ }
65701
+ }
65427
65702
  return patternToken.optional || false;
65428
65703
  }
65429
65704
  return true;
@@ -65716,6 +65991,7 @@ function registerTokenizer2(tokenizer) {
65716
65991
  }
65717
65992
  init_registry();
65718
65993
  init_command_schemas();
65994
+ init_marker_resolution();
65719
65995
  init_registry();
65720
65996
  var OPENER_ACTIONS = ["if", "unless", "repeat", "for", "while"];
65721
65997
  var PASCAL_CASE_NAME = /^[A-Z][A-Za-z0-9_]*$/;
@@ -67734,13 +68010,18 @@ var _SemanticParserImpl = class _SemanticParserImpl2 {
67734
68010
  if (!spec) return true;
67735
68011
  return spec.expectedTypes.length > 0 && !spec.expectedTypes.includes(valType(val));
67736
68012
  };
68013
+ const isMarkerConceptJunk = (role, val) => role === "patient" && !!schema && !schema.roles.some((r) => r.role === "patient") && valType(val) === "literal" && ROLE_MARKER_CONCEPTS.has(
68014
+ String(val.value ?? "").toLowerCase()
68015
+ );
67737
68016
  const preservesFused = !!first && first.kind === "command" && Object.entries(roles).every(([role, val]) => {
67738
- if (isIgnorableFusedRole(role, val)) return true;
68017
+ if (isIgnorableFusedRole(role, val) || isMarkerConceptJunk(role, val)) return true;
67739
68018
  const rv = first.roles.get(mapRole(role));
67740
68019
  if (rv !== void 0 && valType(rv) === valType(val)) return true;
67741
68020
  if (role === "patient" && actionName === "pick" && valType(val) === "literal") {
67742
68021
  const mv = first.roles.get("method");
67743
- return mv !== void 0 && valType(mv) === "literal" && String(mv.value) === String(val.value);
68022
+ const mvType = valType(mv);
68023
+ const mvSurface = mvType === "literal" ? String(mv.value) : mvType === "expression" ? String(mv.raw) : void 0;
68024
+ return mvSurface !== void 0 && mvSurface === String(val.value);
67744
68025
  }
67745
68026
  return false;
67746
68027
  });
@@ -67750,7 +68031,12 @@ var _SemanticParserImpl = class _SemanticParserImpl2 {
67750
68031
  // the swap can never swallow a body command. The body-swallowing
67751
68032
  // generated repeat matches none of these ids.
67752
68033
  /^repeat-.*-(times|for-in|while-head|until-head)$/.test(reparsePid);
67753
- if (reparsed.length === 1 && first && first.kind === "command" && first.action === actionName && preservesFused && headOnlyOk && first.roles.size > Object.keys(roles).length) {
68034
+ if (reparsed.length === 1 && first && first.kind === "command" && first.action === actionName && preservesFused && headOnlyOk && // Strictly-more: the re-parse must recover something the fused
68035
+ // capture lacked. Junk marker captures are excluded from the
68036
+ // count \u2014 a fused shape whose ONLY role is a swallowed marker
68037
+ // (scroll: `destination:literal="destination"`) would otherwise
68038
+ // tie 1 > 1 and veto its own repair.
68039
+ first.roles.size > Object.entries(roles).filter(([r, v2]) => !isMarkerConceptJunk(r, v2)).length) {
67754
68040
  commandNode = first;
67755
68041
  while (tokens.position() < clauseEnd) tokens.advance();
67756
68042
  } else {
@@ -74371,7 +74657,7 @@ function getGetPatternsBn() {
74371
74657
  tokens: [
74372
74658
  { type: "role", role: "source" },
74373
74659
  { type: "literal", value: "\u09A5\u09C7\u0995\u09C7" },
74374
- { type: "literal", value: "\u09AA\u09BE\u09A8", alternatives: ["\u09A8\u09BF\u09A8"] }
74660
+ { type: "literal", value: "\u09AA\u09BE\u09A8" }
74375
74661
  ]
74376
74662
  },
74377
74663
  extraction: {
@@ -74387,7 +74673,7 @@ function getGetPatternsBn() {
74387
74673
  template: {
74388
74674
  format: "\u09AA\u09BE\u09A8 {source}",
74389
74675
  tokens: [
74390
- { type: "literal", value: "\u09AA\u09BE\u09A8", alternatives: ["\u09A8\u09BF\u09A8"] },
74676
+ { type: "literal", value: "\u09AA\u09BE\u09A8" },
74391
74677
  { type: "role", role: "source" }
74392
74678
  ]
74393
74679
  },
@@ -74471,7 +74757,7 @@ function getGetPatternsIt() {
74471
74757
  template: {
74472
74758
  format: "ottenere {patient} da {source}",
74473
74759
  tokens: [
74474
- { type: "literal", value: "ottenere", alternatives: ["ottieni", "get", "prendere"] },
74760
+ { type: "literal", value: "ottenere", alternatives: ["ottieni", "get"] },
74475
74761
  { type: "role", role: "patient" },
74476
74762
  {
74477
74763
  type: "group",
@@ -74561,7 +74847,7 @@ function getGetPatternsRu() {
74561
74847
  template: {
74562
74848
  format: "\u043F\u043E\u043B\u0443\u0447\u0438\u0442\u044C {patient} \u0438\u0437 {source}",
74563
74849
  tokens: [
74564
- { type: "literal", value: "\u043F\u043E\u043B\u0443\u0447\u0438\u0442\u044C", alternatives: ["\u043F\u043E\u043B\u0443\u0447\u0438", "\u0432\u0437\u044F\u0442\u044C", "\u0432\u043E\u0437\u044C\u043C\u0438"] },
74850
+ { type: "literal", value: "\u043F\u043E\u043B\u0443\u0447\u0438\u0442\u044C", alternatives: ["\u043F\u043E\u043B\u0443\u0447\u0438"] },
74565
74851
  { type: "role", role: "patient" },
74566
74852
  {
74567
74853
  type: "group",
@@ -74586,7 +74872,7 @@ function getGetPatternsRu() {
74586
74872
  template: {
74587
74873
  format: "\u043F\u043E\u043B\u0443\u0447\u0438\u0442\u044C {patient}",
74588
74874
  tokens: [
74589
- { type: "literal", value: "\u043F\u043E\u043B\u0443\u0447\u0438\u0442\u044C", alternatives: ["\u043F\u043E\u043B\u0443\u0447\u0438", "\u0432\u0437\u044F\u0442\u044C", "\u0432\u043E\u0437\u044C\u043C\u0438"] },
74875
+ { type: "literal", value: "\u043F\u043E\u043B\u0443\u0447\u0438\u0442\u044C", alternatives: ["\u043F\u043E\u043B\u0443\u0447\u0438"] },
74590
74876
  { type: "role", role: "patient" }
74591
74877
  ]
74592
74878
  },
@@ -74627,7 +74913,7 @@ function getGetPatternsUk() {
74627
74913
  template: {
74628
74914
  format: "\u043E\u0442\u0440\u0438\u043C\u0430\u0442\u0438 {patient} \u0437 {source}",
74629
74915
  tokens: [
74630
- { type: "literal", value: "\u043E\u0442\u0440\u0438\u043C\u0430\u0442\u0438", alternatives: ["\u043E\u0442\u0440\u0438\u043C\u0430\u0439", "\u0432\u0437\u044F\u0442\u0438", "\u0432\u0456\u0437\u044C\u043C\u0438"] },
74916
+ { type: "literal", value: "\u043E\u0442\u0440\u0438\u043C\u0430\u0442\u0438", alternatives: ["\u043E\u0442\u0440\u0438\u043C\u0430\u0439"] },
74631
74917
  { type: "role", role: "patient" },
74632
74918
  {
74633
74919
  type: "group",
@@ -74652,7 +74938,7 @@ function getGetPatternsUk() {
74652
74938
  template: {
74653
74939
  format: "\u043E\u0442\u0440\u0438\u043C\u0430\u0442\u0438 {patient}",
74654
74940
  tokens: [
74655
- { type: "literal", value: "\u043E\u0442\u0440\u0438\u043C\u0430\u0442\u0438", alternatives: ["\u043E\u0442\u0440\u0438\u043C\u0430\u0439", "\u0432\u0437\u044F\u0442\u0438", "\u0432\u0456\u0437\u044C\u043C\u0438"] },
74941
+ { type: "literal", value: "\u043E\u0442\u0440\u0438\u043C\u0430\u0442\u0438", alternatives: ["\u043E\u0442\u0440\u0438\u043C\u0430\u0439"] },
74656
74942
  { type: "role", role: "patient" }
74657
74943
  ]
74658
74944
  },
@@ -74672,7 +74958,7 @@ function getGetPatternsVi() {
74672
74958
  template: {
74673
74959
  format: "l\u1EA5y gi\xE1 tr\u1ECB c\u1EE7a {target}",
74674
74960
  tokens: [
74675
- { type: "literal", value: "l\u1EA5y gi\xE1 tr\u1ECB", alternatives: ["nh\u1EADn", "l\u1EA5y"] },
74961
+ { type: "literal", value: "l\u1EA5y gi\xE1 tr\u1ECB", alternatives: ["nh\u1EADn"] },
74676
74962
  { type: "group", optional: true, tokens: [{ type: "literal", value: "c\u1EE7a" }] },
74677
74963
  { type: "role", role: "patient" }
74678
74964
  ]
@@ -74683,13 +74969,17 @@ function getGetPatternsVi() {
74683
74969
  },
74684
74970
  {
74685
74971
  id: "get-vi-simple",
74972
+ // Head was `l\u1ea5y` (alt `l\u1ea5y gi\u00e1 tr\u1ecb`) \u2014 but bare `l\u1ea5y` is vi's TAKE verb,
74973
+ // so this pattern claimed every `l\u1ea5y .active t\u1eeb \u2026`. vi's get verb is the
74974
+ // three-word `l\u1ea5y gi\u00e1 tr\u1ecb` ("take the value of"), which is what the i18n
74975
+ // transformer renders; the bare form has no valid `get` surface.
74686
74976
  language: "vi",
74687
74977
  command: "get",
74688
74978
  priority: 90,
74689
74979
  template: {
74690
- format: "l\u1EA5y {target}",
74980
+ format: "l\u1EA5y gi\xE1 tr\u1ECB {target}",
74691
74981
  tokens: [
74692
- { type: "literal", value: "l\u1EA5y", alternatives: ["nh\u1EADn", "l\u1EA5y gi\xE1 tr\u1ECB"] },
74982
+ { type: "literal", value: "l\u1EA5y gi\xE1 tr\u1ECB", alternatives: ["nh\u1EADn"] },
74693
74983
  { type: "role", role: "patient" }
74694
74984
  ]
74695
74985
  },
@@ -76428,6 +76718,12 @@ function getSendPatternsForLanguage(language) {
76428
76718
  return [];
76429
76719
  }
76430
76720
  }
76721
+ var PICK_UNIT_WORDS = /* @__PURE__ */ new Set(["character", "characters", "item", "items"]);
76722
+ var retypePickUnitWord = (raw) => {
76723
+ if (PICK_UNIT_WORDS.has(raw)) return { type: "expression", raw };
76724
+ const n = Number(raw);
76725
+ return createLiteral(raw !== "" && !Number.isNaN(n) ? n : raw);
76726
+ };
76431
76727
  function makePickVariantPattern(language, spec) {
76432
76728
  const tokens = [{ type: "literal", value: "pick" }];
76433
76729
  if (spec.objectMarkers?.length) {
@@ -76467,7 +76763,7 @@ function makePickVariantPattern(language, spec) {
76467
76763
  tokens
76468
76764
  },
76469
76765
  extraction: {
76470
- method: { position: 1 },
76766
+ method: { position: 1, transform: retypePickUnitWord },
76471
76767
  patient: { position: 2 },
76472
76768
  source: {
76473
76769
  marker: spec.srcMarker,
@@ -76518,7 +76814,7 @@ function makePickVerbFinalPattern(language, spec) {
76518
76814
  },
76519
76815
  extraction: {
76520
76816
  source: { position: 0 },
76521
- method: { position: 2 },
76817
+ method: { position: 2, transform: retypePickUnitWord },
76522
76818
  patient: { position: 3 }
76523
76819
  }
76524
76820
  };
@@ -86429,4 +86725,4 @@ export {
86429
86725
  toCoreAST,
86430
86726
  validatePartialContent
86431
86727
  };
86432
- //# sourceMappingURL=dist-VGR6QDPB.js.map
86728
+ //# sourceMappingURL=dist-I7VYJWBF.js.map