@aria-framework/ask 0.1.0 → 0.1.1

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
@@ -1,5 +1,21 @@
1
1
  # @aria-framework/ask
2
2
 
3
+ ## 0.1.1 — 2026-11-03
4
+
5
+ Fix: the answer check refused every multi-sentence answer that cites before a full stop — the shape the answer rules ask
6
+ for. A cite or placeholder was replaced by a space, so "Waiting on us [r1]. It" read "us . It"; the spaced-dot rule
7
+ (0.1.0's re-review) joined that into "us.It", a domain, and the answer was withheld as `link` (the desk's bench: 41 such
8
+ failures, payload-free twins included; real tokens `us.It`, `Logistics.This`, `agents.Thandi`).
9
+
10
+ - A run of cites/placeholders directly before `. , ; : ! ?` is now removed WITH the whitespace before it ("us [r1]."
11
+ reads "us."); a run directly after one of those and directly before a non-space is removed too ("evil.[r1]Com" reads
12
+ "evil.Com"). Elsewhere a mark is still a space. Both only join text onto punctuation, so `evil [r1].com`,
13
+ `evil [r1]. com`, `evil [r1] .com`, `evil{{r1}}.com` and the NBSP / newline / fullwidth / ideographic variants stay
14
+ `link`. `SPACED_DOT` and `DOMAINISH` are unchanged. "evil [r1]. Com" reads as the prose "evil. Com" and gets its verdict.
15
+ - Both new rules are in the check's `RULE_SOURCES`.
16
+ - **The scorer hash moves** (the check's fingerprint is in it): every app's stored bench record stops being `usable()`,
17
+ so every app re-benches once after pinning 0.1.1. The prompt hash and the catalogue hash do not move.
18
+
3
19
  ## 0.1.0 — 2026-11-02
4
20
 
5
21
  First release: extracted from the hub's (0.97.2) and soc's (0.89.5) copies of Ask anything, taking the
package/lib/check.js CHANGED
@@ -38,6 +38,14 @@
38
38
 
39
39
  const PLACEHOLDER = /\{\{\s*(r[1-4])(?:\.([a-z0-9_]{1,40}))?\s*\}\}/g;
40
40
  const CITE = /\[(r[1-4])\]/g;
41
+ // A CITE OR PLACEHOLDER AGAINST PUNCTUATION (0.1.1). Replaced by a space, "Waiting on us [r1]. It" read "us . It", which
42
+ // SPACED_DOT joins into "us.It" — a domain — so every answer that cites before a full stop was refused as `link`. A run of
43
+ // marks directly before . , ; : ! ? goes WITH the whitespace before it ("us [r1]." reads "us."); a run directly after one
44
+ // of them and directly before a non-space goes too ("evil.[r1]Com" reads "evil.Com", not "evil. Com"). Both only ever
45
+ // JOIN text onto punctuation, so "evil [r1].com" reads "evil.com" and is still a domain. Everywhere else: a space.
46
+ const MARK = String.raw`(?:\{\{\s*r[1-4](?:\.[a-z0-9_]{1,40})?\s*\}\}|\[r[1-4]\])`;
47
+ const MARK_BEFORE_PUNCT = new RegExp(String.raw`(?:\s*${MARK})+(?=[.,;:!?])`, 'g');
48
+ const MARK_AFTER_DOT = new RegExp(String.raw`(?<=[.,;:!?])${MARK}+(?=\S)`, 'g');
41
49
  const DIGIT_TOKEN = /[\p{L}\p{N}_.:\-/]*\p{N}[\p{L}\p{N}_.:\-/]*/gu;
42
50
  const PURE_NUMBER = /^[\p{N}.,]+$/u;
43
51
  const REF_TOKEN = /(?<![\p{L}\p{N}])[\p{L}]{2,5}_[\p{L}\p{N}]{4,}/gu;
@@ -249,7 +257,7 @@ function createCheck(o = {}) {
249
257
  for (const c of reply.cites) if (!/^r[1-4]$/.test(c) || !results[Number(c.slice(1)) - 1]) return { ok: false, code: 'unknown_cite', reason: `cites ${String(c).slice(0, 8)}, which no look-up returned` };
250
258
  for (const m of answer.matchAll(CITE)) if (!results[Number(m[1].slice(1)) - 1]) return { ok: false, code: 'unknown_cite', reason: `cites ${m[1]}, which no look-up returned` };
251
259
  for (const m of answer.matchAll(PLACEHOLDER)) if (!figureOf(results, m[1], m[2])) return { ok: false, code: 'unknown_figure', reason: `a figure ${m[0]} no look-up returned` };
252
- const bare = answer.replace(PLACEHOLDER, ' ').replace(CITE, ' ');
260
+ const bare = answer.replace(MARK_BEFORE_PUNCT, '').replace(MARK_AFTER_DOT, '').replace(PLACEHOLDER, ' ').replace(CITE, ' ');
253
261
  if (/[{}]/.test(bare)) return { ok: false, code: 'bad_placeholder', reason: 'a malformed figure placeholder' };
254
262
  // NFKC, other full stops and NO format characters for the word rules: what the person would read.
255
263
  const norm = readable(bare);
@@ -343,7 +351,7 @@ function createCheck(o = {}) {
343
351
 
344
352
  /** Every module-level rule and helper a verdict depends on, as text (with createCheck's own source). */
345
353
  const RULE_SOURCES = [PLACEHOLDER, CITE, DIGIT_TOKEN, PURE_NUMBER, REF_TOKEN, HOSTLIKE, LINKISH, DOMAINISH, INTERNAL_SUFFIX, NUMBER_WORD, IPV4, IPV6, WINDOW,
346
- INVISIBLE, OTHER_DOTS, BRACKETED_DOT, SPELLED_DOT, SPACED_DOT, ALLOWED_CHAR, ...OBEYED.map(([re, why, code]) => `${re}|${why}|${code}`), REFUSAL_CODES.join(','),
354
+ MARK_BEFORE_PUNCT, MARK_AFTER_DOT, INVISIBLE, OTHER_DOTS, BRACKETED_DOT, SPELLED_DOT, SPACED_DOT, ALLOWED_CHAR, ...OBEYED.map(([re, why, code]) => `${re}|${why}|${code}`), REFUSAL_CODES.join(','),
347
355
  unitOf, isInternalHost, readable, trim, stringsOf, figureOf, segmentsOf, helpChips, createCheck].map(String);
348
356
 
349
357
  module.exports = { createCheck, REFUSAL_CODES, NUMBER_WORD, REF_TOKEN, PLACEHOLDER, LINKISH, segmentsOf, figureOf, stringsOf, readable };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aria-framework/ask",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Aria App Framework — ask module. \"Ask anything\": a read-only question box over an app's own records — plan, run the app's tools in the asker's own request, answer from fenced results, check every figure and link, audit. Ships the loop, the answer check, the bench, canonical settings, the question model factory, a reference table design with its generator and check, the ask/1 stream, route factories, views and the drawer script. The app supplies its tools and words.",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,