New:Socket for Asana Is Now Available.Learn more
Get Started

@lubab/madar

Package Overview
Dependencies
Maintainers
1
Versions
49
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@lubab/madar - npm Package Compare versions

Comparing version
0.40.0-beta.6
to
0.40.0-beta.7
+72
-72
dist/src/domain/query/plan.js

@@ -7,21 +7,21 @@ const OWNER = 'file|module|class|function|method|service|handler|worker|component|controller|repository';

const IRREGULAR = new Map('built=build generation=generate got=get getting=get persistence=persist planned=plan planning=plan ran=run running=run setting=set written=write wrote=write'.split(' ').map((pair) => pair.split('=')));
function canonical(value) {
const mapped = IRREGULAR.get(value);
if (mapped)
return mapped;
const ing = value.endsWith('ing') ? value.slice(0, -3) : '';
const past = value.endsWith('ed') ? value.slice(0, -2) : '';
const forms = [value,
/i(?:es|ed)$/u.test(value) ? `${value.slice(0, -3)}y` : '',
function canon(v) {
const m = IRREGULAR.get(v);
if (m)
return m;
const ing = v.endsWith('ing') ? v.slice(0, -3) : '';
const past = v.endsWith('ed') ? v.slice(0, -2) : '';
const f = [v,
/i(?:es|ed)$/u.test(v) ? `${v.slice(0, -3)}y` : '',
ing, ing ? `${ing}e` : '', past, past ? `${past}e` : '',
value.endsWith('es') ? value.slice(0, -2) : '',
value.endsWith('s') ? value.slice(0, -1) : ''];
const action = forms.find((candidate) => ACTIONS.has(candidate));
if (action)
return action;
if (value.length <= 4)
return value;
if (value.endsWith('ies'))
return `${value.slice(0, -3)}y`;
return /(?<!s|u|i)s$/u.test(value) ? value.slice(0, -1) : value;
v.endsWith('es') ? v.slice(0, -2) : '',
v.endsWith('s') ? v.slice(0, -1) : ''];
const a = f.find((x) => ACTIONS.has(x));
if (a)
return a;
if (v.length <= 4)
return v;
if (v.endsWith('ies'))
return `${v.slice(0, -3)}y`;
return /(?<!s|u|i)s$/u.test(v) ? v.slice(0, -1) : v;
}

@@ -33,3 +33,3 @@ export function lexicalTokens(value) {

.toLowerCase();
return (raw.match(/[\p{L}\p{N}]+/gu) ?? []).map(canonical);
return (raw.match(/[\p{L}\p{N}]+/gu) ?? []).map(canon);
}

@@ -46,9 +46,9 @@ const [FW, LW, EW] = [FLOW, LOCATE, EXPLAIN].map((set) => [...set].join('|'));

for (const rule of rules) {
const topic = content(rule.exec(text)?.slice(1).join(' ') ?? '', mode, plain).join(' ');
if (topic)
return topic;
const hit = content(rule.exec(text)?.slice(1).join(' ') ?? '', mode, plain).join(' ');
if (hit)
return hit;
}
return '';
}
function coordinatedFlow(text) {
function flow(text) {
const entry = /\b(?:accept|receive|submit|handle) (.+?)(?= (?:schedule|enqueue|queue|dispatch|research|process|compose|assemble|render|write|save|store|persist)\b)/u

@@ -59,11 +59,11 @@ .exec(text), end = /\b(?:write|save|store|persist) (.+)$/u.exec(text), composed = /\b(compose|assemble|render) (.+?)(?= (?:and )?(?:write|save|store|persist)\b|$)/u

return undefined;
const input = content(entry[1], 'workflow');
let output = content(composed?.[2] ?? end[1], 'workflow');
if (composed && /^(?:model|output|result)$/u.test(output.at(-1) ?? ''))
output = content(end[1], 'workflow');
const first = input[0], raw = output.at(-1), last = /^(?:model|output|result)$/u.test(raw ?? '') ? first : raw;
const ins = content(entry[1], 'workflow');
let outs = content(composed?.[2] ?? end[1], 'workflow');
if (composed && /^(?:model|output|result)$/u.test(outs.at(-1) ?? ''))
outs = content(end[1], 'workflow');
const first = ins[0], raw = outs.at(-1), last = /^(?:model|output|result)$/u.test(raw ?? '') ? first : raw;
if (!first || !last)
return undefined;
const handoff = /\b(?:schedule|enqueue|queue|dispatch|publish|emit)\b/u.test(text)
? 'schedule' : undefined, stages = [
const hop = /\b(?:schedule|enqueue|queue|dispatch|publish|emit)\b/u.test(text)
? 'schedule' : undefined, steps = [
/\b(?:research|investigate|discover)\b/u.test(text) ? 'research' : '',

@@ -75,8 +75,8 @@ /\b(?:compose|assemble|render|synthesize|merge)\b/u.test(text)

subject: first === last ? first : `${first} ${last}`,
entry: `request ${first}`, ...(stages.length ? { stage: stages.join(' ') } : {}),
...(handoff ? { handoff } : {}), terminal: 'persistence',
terms: [...new Set([first, last, ...stages, ...(handoff ? [handoff] : [])])],
entry: `request ${first}`, ...(steps.length ? { stage: steps.join(' ') } : {}),
...(hop ? { handoff: hop } : {}), terminal: 'persistence',
terms: [...new Set([first, last, ...steps, ...(hop ? [hop] : [])])],
};
}
function flowSubject(text) {
function subject(text) {
const direct = pick(text, 'workflow', [

@@ -101,3 +101,3 @@ /\bwhat happen when (?:(?:a|an|the) )?(?:user|client|caller) (?:request|submit) (.+)$/,

}
const topic = pick(text, 'workflow', [
const subj = pick(text, 'workflow', [
/^follow (?:\S+ )*?(\S+) from .+ until (?:\S+ )*?(\S+) is/,

@@ -111,5 +111,5 @@ /for (.+?) generate/,

]);
return [topic || content(text, 'workflow').join(' '), []];
return [subj || content(text, 'workflow').join(' '), []];
}
function flowBounds(text) {
function bounds(text, s = false) {
if (/^follow /.test(text)

@@ -119,5 +119,4 @@ || !(/\b(?:from|via)\b/u.test(text) || /^(?:trace|walk)\b.*\bthrough\b/u

return {};
const read = (rule) => {
const value = lexicalTokens(rule.exec(text)?.[1] ?? '')
.filter((token) => !COMMON.has(token)).join(' ');
const read = (r) => {
const value = lexicalTokens(r.exec(text)?.[1] ?? '').filter((token) => !COMMON.has(token)).join(' ');
return value || undefined;

@@ -132,6 +131,6 @@ };

: read(/\bthrough (?!to\b)(.+?)(?= to\b| how\b|$)/u)),
terminal: read(/(?<!end )\b(?:through )?to (.+?)(?= how\b|$)/u)?.replace(/^save (?=report$)/u, ''),
terminal: read(/(?<!end )\b(?:through )?to (.+?)(?= how\b|$)/u)?.replace(s ? /^(?:save|finished|done) (?=report$)/u : /^save (?=report$)/u, ''),
};
}
function simpleSubject(text, mode) {
function simple(text, mode) {
const locate = mode === 'locate';

@@ -154,7 +153,8 @@ const rules = locate ? [

export function planQuestion(request) {
const raw = request.question.normalize('NFKC'), text = lexicalTokens(request.question).join(' '), tokens = text.split(' '), names = [...raw.matchAll(/(?<![\p{L}\p{N}_$])([\p{L}_$][\p{L}\p{N}_$]*(?:\.[\p{L}_$][\p{L}\p{N}_$]*)+)/gu)]
.map((match) => match[1]), ident = /\bwhere\s+(?:is|are|was|were)\s+[`'"]?([\p{L}_$][\p{L}\p{N}_$.-]*)[`'"]?\s+(?:defined|declared|implemented)\b/iu
.exec(raw)?.[1], ownerQuery = RegExp(`\\b(?:which|what) (?:${OWNER}) (?:${LW})\\b`).test(text);
const mode = ownerQuery ? 'locate'
: /\b(?:end to end|what happen when)\b|\bfrom\b.+\b(?:through|via)\b.+\bto\b|\btrace\b.+\bfrom\b.+\bto\b/.test(text)
const raw = request.question.normalize('NFKC'), text = lexicalTokens(request.question).join(' '), tokens = text.split(' '), refs = [...raw.matchAll(/(?<![\p{L}\p{N}_$])([\p{L}_$][\p{L}\p{N}_$]*(?:\.[\p{L}_$][\p{L}\p{N}_$]*)+)/gu)]
.map((match) => match[1]), id = /\bwhere\s+(?:is|are|was|were)\s+[`'"]?([\p{L}_$][\p{L}\p{N}_$.-]*)[`'"]?\s+(?:defined|declared|implemented)\b/iu
.exec(raw)?.[1], owner = RegExp(`\\b(?:which|what) (?:${OWNER}) (?:${LW})\\b`).test(text);
const mode = owner ? 'locate'
: /^where (?:is|are|was|were) .+ (?:flow|workflow|pipeline) orchestrated list (?:the )?(?:flow|workflow|pipeline) stage and (?:the )?entrypoint (?:service|handler|worker)$/u.test(text)
|| /\b(?:end to end|what happen when)\b|\bfrom\b.+\b(?:through|via)\b.+\bto\b|\btrace\b.+\bfrom\b.+\bto\b/.test(text)
|| /^follow /.test(text)

@@ -178,21 +178,21 @@ || /^which .+\b(?:save|write)\b/.test(text)

}
const coordinated = mode === 'workflow' ? coordinatedFlow(text) : undefined;
const [topic, ignored] = mode === 'workflow'
? coordinated ? [coordinated.subject, []] : flowSubject(text)
: [names[0]
? content(names[0], mode, true).join(' ')
: mode === 'locate' && ident
? content(ident, 'locate', true).join(' ')
: simpleSubject(text, mode), []];
const span = coordinated
?? (mode === 'workflow' ? flowBounds(text) : {});
if (mode === 'workflow' && names.length) {
span.stage = names.flatMap(lexicalTokens).join(' ');
const coord = mode === 'workflow' ? flow(text) : undefined;
const [subj, omit] = mode === 'workflow'
? coord ? [coord.subject, []] : subject(text)
: [refs[0]
? content(refs[0], mode, true).join(' ')
: mode === 'locate' && id
? content(id, 'locate', true).join(' ')
: simple(text, mode), []];
const span = coord ?? (mode === 'workflow'
? bounds(text, /(?:^|\s)to\s+(?:(?:a|an|the|its)\s+)?(?:finished|done)\s+report\s*[.?!]*$/iu.test(raw)) : {});
if (mode === 'workflow' && refs.length) {
span.stage = refs.flatMap(lexicalTokens).join(' ');
}
const skip = new Set(ignored);
const terms = new Set((coordinated?.terms ?? tokens).filter((token) => !isNoise(token, mode) && !skip.has(token)));
lexicalTokens(topic).forEach((token) => terms.add(token));
const sorted = [...terms].sort();
if (!topic || sorted.length === 0) {
return { status: 'unsupported', reason: 'missing_subject', terms: sorted };
const skip = new Set(omit);
const keys = new Set((coord?.terms ?? tokens).filter((token) => !isNoise(token, mode) && !skip.has(token)));
lexicalTokens(subj).forEach((token) => keys.add(token));
const list = [...keys].sort();
if (!subj || list.length === 0) {
return { status: 'unsupported', reason: 'missing_subject', terms: list };
}

@@ -209,15 +209,15 @@ const words = new Set(tokens);

.test(text) ? []
: sorted.filter((token) => !lexicalTokens(topic).includes(token));
: list.filter((token) => !lexicalTokens(subj).includes(token));
return {
status: 'supported',
plan: {
intent: mode, subject: topic, terms: sorted,
intent: mode, subject: subj, terms: list,
obligations: kinds.map((kind, index) => ({
id: `o${index + 1}`, kind,
target: kind === 'entry' ? span.entry ?? topic
: kind === 'stage' ? span.stage ?? topic
: kind === 'handoff' ? span.handoff ?? topic
: kind === 'terminal' ? span.terminal ?? topic
target: kind === 'entry' ? span.entry ?? subj
: kind === 'stage' ? span.stage ?? subj
: kind === 'handoff' ? span.handoff ?? subj
: kind === 'terminal' ? span.terminal ?? subj
: kind === 'behavior' && mode === 'explain' && rest.length
? rest.join(' ') : topic,
? rest.join(' ') : subj,
mandatory: true,

@@ -224,0 +224,0 @@ })),

{
"name": "@lubab/madar",
"version": "0.40.0-beta.6",
"version": "0.40.0-beta.7",
"mcpName": "io.github.mohanagy/madar",

@@ -5,0 +5,0 @@ "description": "Give AI coding agents a small, authenticated evidence path through large TypeScript and JavaScript repositories.",

@@ -15,3 +15,3 @@ # Madar

[![npm next](https://img.shields.io/npm/v/%40lubab%2Fmadar/next?label=npm%20next)](https://www.npmjs.com/package/@lubab/madar/v/0.40.0-beta.6)
[![npm next](https://img.shields.io/npm/v/%40lubab%2Fmadar/next?label=npm%20next)](https://www.npmjs.com/package/@lubab/madar/v/0.40.0-beta.7)
[![node >=20](https://img.shields.io/badge/node-%E2%89%A520-3c873a)](https://nodejs.org/)

@@ -23,3 +23,3 @@ [![local first](https://img.shields.io/badge/local--first-no%20cloud%20required-0f766e)](#local-by-design)

See [beta.6 changes](https://github.com/mohanagy/madar/blob/next/CHANGELOG.md#0400-beta6---2026-08-02). This corrective manual-test candidate precedes #631 qualification; it makes no comparative performance or retention claim.
See [beta.7 changes](https://github.com/mohanagy/madar/blob/next/CHANGELOG.md#0400-beta7---2026-08-02). This terminal-language corrective manual-test candidate precedes #631 qualification; it makes no comparative performance or retention claim.

@@ -26,0 +26,0 @@ ## Start in three steps