@ngockhoale/ukit 2.3.21 → 2.3.22

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/CHANGELOG.md CHANGED
@@ -2,6 +2,31 @@
2
2
 
3
3
  All notable changes to UKit are documented here.
4
4
 
5
+ ## 2.3.22 - 2026-09-13
6
+
7
+ Consultation-question routing fix — pure questions no longer fabricate mutation debt that the
8
+ completion gate then enforces against an answer turn. Observed live the same day: two Vietnamese
9
+ consultation questions (no English signal word, no target file) scored every candidate mode ≤ 0,
10
+ the mode ladder's upward bias resolved the find-cause/shared-edit tie to `shared-edit`, and the
11
+ gate blocked the answer turn six times ("missing write-evidence / verification-evidence") until
12
+ the continuation cap released it.
13
+
14
+ - **Consultation questions carry no completion contract.** A question-shaped prompt (trailing `?`,
15
+ a leading English or ASCII-folded Vietnamese interrogative, or a `là gì / được không` tail) with
16
+ no implement/review/debug/failure/impact signal and no target file routes `informational` — the
17
+ same no-mutation-debt lane delivery-only requests already use. Applied to
18
+ `src/index/taskRouting.js`, the standalone router `route-task.mjs`, and the hook-embedded
19
+ routing copy in `skill-router.sh` (live twins byte-identical).
20
+ - **Leading interrogatives override action words.** The router's signal regexes are English-only,
21
+ so Vietnamese how-questions mentioning an action ("Làm sao mà đo được khi tôi cài hệ thống
22
+ này…?") kept a mutation contract. A leading interrogative (làm sao / thế nào / tại sao / phải
23
+ làm gì / …) now marks the prompt consultative even when it contains implement verbs
24
+ (sửa / thêm / cài / cài đặt / …) — asking HOW something is done is not ordering the action
25
+ performed. Question-phrased edit orders ("bạn sửa giúp tôi… không?") keep their write contract.
26
+ - **Verification.** New routing regressions lock the two incident prompts to `informational` with
27
+ empty contract evidence, and lock both guard directions (English signal-word questions and
28
+ question-phrased Vietnamese edit orders stay in their lanes); full suite green.
29
+
5
30
  ## 2.3.21 - 2026-09-13
6
31
 
7
32
  C16 release — the prompt-caching ruleset turns from research into shipped guidance, and the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ngockhoale/ukit",
3
- "version": "2.3.21",
3
+ "version": "2.3.22",
4
4
  "description": "Install/update an index-first AI workspace for Claude Code, OpenAI Codex, OpenCode, and omp (Oh My Pi).",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -452,6 +452,47 @@ function deriveExecutionMode({
452
452
  && !scores.smallFixSignal
453
453
  && !scores.sharedRisk
454
454
  && !targetFile;
455
+ // A pure consultation question ("Rồi việc kế tiếp của tôi phải làm gì…?", "how do I
456
+ // measure this on another machine?") asks for an answer, not a repository change. The
457
+ // signal regexes are English-only, so a Vietnamese (or signal-free English) question
458
+ // with no target file scores every candidate mode ≤ 0 and the ladder's upward bias
459
+ // resolves the 0-score find-cause/shared-edit tie to shared-edit — fabricating
460
+ // write+verification debt that a text answer can never satisfy, after which the
461
+ // completion gate blocks the answer turn until the continuation cap releases it.
462
+ // Consultation questions carry no completion contract instead. A question that also
463
+ // carries an implement/review/debug/failure signal keeps its lane; targeted questions
464
+ // (explicit file target) keep their contract so a Vietnamese edit order against a
465
+ // named file stays enforced.
466
+ const trimmedPromptText = String(promptText || '').trim();
467
+ const foldedPromptText = trimmedPromptText
468
+ .toLowerCase()
469
+ .normalize('NFD')
470
+ .replace(/[\u0300-\u036f]/g, '')
471
+ .replace(/\u0111/g, 'd');
472
+ const leadingInterrogative = /^(?:what|how|which|when|where|who)\b/.test(foldedPromptText)
473
+ || /^(?:lam sao|the nao|nhu the nao|nhu nao|vi sao|tai sao|khi nao|bao gio|bao nhieu|o dau|phai lam gi|lam gi|lam cach nao)\b/.test(foldedPromptText);
474
+ const questionShapedPrompt = /\?\s*$/.test(trimmedPromptText)
475
+ || leadingInterrogative
476
+ || /\b(?:la gi|duoc khong)\s*$/.test(foldedPromptText);
477
+ // Implement verbs (Vietnamese included — the English-only scores above cannot see
478
+ // them) mark an action order even when phrased as a question ("ban sua giup toi…?" is
479
+ // an edit order, not a consultation). A leading interrogative overrides them:
480
+ // "Lam sao ma do duoc khi toi cai…?" asks HOW something is done, it does not order
481
+ // the action performed.
482
+ const consultationImplementWords = /(?<![A-Za-z0-9_])(?:implement|apply|update|modify|add|create|ship|deliver|fix|refactor|remove|delete|rename|change|write|build|make|install|run|deploy|execute|sửa|thêm|tạo|xóa|đổi|thay thế|cập nhật|viết|chạy|cài)(?![A-Za-z0-9_])/.test(trimmedPromptText);
483
+ const consultationOnlySignal = questionShapedPrompt
484
+ && (leadingInterrogative || !consultationImplementWords)
485
+ && scores.editCertainty === 0
486
+ && !scores.implementSignal
487
+ && !scores.reviewSignal
488
+ && !scores.debugSignal
489
+ && !scores.failureSignal
490
+ && !scores.impactSignal
491
+ && !scores.buildSignal
492
+ && !scores.directTransformSignal
493
+ && !scores.smallFixSignal
494
+ && !scores.sharedRisk
495
+ && !targetFile;
455
496
 
456
497
  if (
457
498
  releaseVerificationContinuation
@@ -460,7 +501,7 @@ function deriveExecutionMode({
460
501
  return 'review-release';
461
502
  }
462
503
 
463
- if (deliveryOnlySignal) {
504
+ if (deliveryOnlySignal || consultationOnlySignal) {
464
505
  return 'informational';
465
506
  }
466
507
 
@@ -1652,7 +1652,38 @@ const { pathToFileURL } = require('url');
1652
1652
  return 'review-release';
1653
1653
  }
1654
1654
 
1655
- if (deliveryOnlySignal) {
1655
+ const trimmedPromptText = String(promptText || '').trim();
1656
+ const foldedPromptText = trimmedPromptText
1657
+ .toLowerCase()
1658
+ .normalize('NFD')
1659
+ .replace(/[\u0300-\u036f]/g, '')
1660
+ .replace(/\u0111/g, 'd');
1661
+ const leadingInterrogative = /^(?:what|how|which|when|where|who)\b/.test(foldedPromptText)
1662
+ || /^(?:lam sao|the nao|nhu the nao|nhu nao|vi sao|tai sao|khi nao|bao gio|bao nhieu|o dau|phai lam gi|lam gi|lam cach nao)\b/.test(foldedPromptText);
1663
+ const questionShapedPrompt = /\?\s*$/.test(trimmedPromptText)
1664
+ || leadingInterrogative
1665
+ || /\b(?:la gi|duoc khong)\s*$/.test(foldedPromptText);
1666
+ // Implement verbs (Vietnamese included — the English-only scores above cannot see
1667
+ // them) mark an action order even when phrased as a question ("ban sua giup toi…?" is
1668
+ // an edit order, not a consultation). A leading interrogative overrides them:
1669
+ // "Lam sao ma do duoc khi toi cai…?" asks HOW something is done, it does not order
1670
+ // the action performed.
1671
+ const consultationImplementWords = /(?<![A-Za-z0-9_])(?:implement|apply|update|modify|add|create|ship|deliver|fix|refactor|remove|delete|rename|change|write|build|make|install|run|deploy|execute|sửa|thêm|tạo|xóa|đổi|thay thế|cập nhật|viết|chạy|cài)(?![A-Za-z0-9_])/.test(trimmedPromptText);
1672
+ const consultationOnlySignal = questionShapedPrompt
1673
+ && (leadingInterrogative || !consultationImplementWords)
1674
+ && scores.editCertainty === 0
1675
+ && !scores.implementSignal
1676
+ && !scores.reviewSignal
1677
+ && !scores.debugSignal
1678
+ && !scores.failureSignal
1679
+ && !scores.impactSignal
1680
+ && !scores.buildSignal
1681
+ && !scores.directTransformSignal
1682
+ && !scores.smallFixSignal
1683
+ && !scores.sharedRisk
1684
+ && !targetFile;
1685
+
1686
+ if (deliveryOnlySignal || consultationOnlySignal) {
1656
1687
  return 'informational';
1657
1688
  }
1658
1689
 
@@ -1832,7 +1832,38 @@ function deriveExecutionMode({
1832
1832
  return 'review-release';
1833
1833
  }
1834
1834
 
1835
- if (deliveryOnlySignal) {
1835
+ const trimmedPromptText = String(promptText || '').trim();
1836
+ const foldedPromptText = trimmedPromptText
1837
+ .toLowerCase()
1838
+ .normalize('NFD')
1839
+ .replace(/[\u0300-\u036f]/g, '')
1840
+ .replace(/\u0111/g, 'd');
1841
+ const leadingInterrogative = /^(?:what|how|which|when|where|who)\b/.test(foldedPromptText)
1842
+ || /^(?:lam sao|the nao|nhu the nao|nhu nao|vi sao|tai sao|khi nao|bao gio|bao nhieu|o dau|phai lam gi|lam gi|lam cach nao)\b/.test(foldedPromptText);
1843
+ const questionShapedPrompt = /\?\s*$/.test(trimmedPromptText)
1844
+ || leadingInterrogative
1845
+ || /\b(?:la gi|duoc khong)\s*$/.test(foldedPromptText);
1846
+ // Implement verbs (Vietnamese included — the English-only scores above cannot see
1847
+ // them) mark an action order even when phrased as a question ("ban sua giup toi…?" is
1848
+ // an edit order, not a consultation). A leading interrogative overrides them:
1849
+ // "Lam sao ma do duoc khi toi cai…?" asks HOW something is done, it does not order
1850
+ // the action performed.
1851
+ const consultationImplementWords = /(?<![A-Za-z0-9_])(?:implement|apply|update|modify|add|create|ship|deliver|fix|refactor|remove|delete|rename|change|write|build|make|install|run|deploy|execute|sửa|thêm|tạo|xóa|đổi|thay thế|cập nhật|viết|chạy|cài)(?![A-Za-z0-9_])/.test(trimmedPromptText);
1852
+ const consultationOnlySignal = questionShapedPrompt
1853
+ && (leadingInterrogative || !consultationImplementWords)
1854
+ && scores.editCertainty === 0
1855
+ && !scores.implementSignal
1856
+ && !scores.reviewSignal
1857
+ && !scores.debugSignal
1858
+ && !scores.failureSignal
1859
+ && !scores.impactSignal
1860
+ && !scores.buildSignal
1861
+ && !scores.directTransformSignal
1862
+ && !scores.smallFixSignal
1863
+ && !scores.sharedRisk
1864
+ && !targetFile;
1865
+
1866
+ if (deliveryOnlySignal || consultationOnlySignal) {
1836
1867
  return 'informational';
1837
1868
  }
1838
1869