feat(ms-ai-architect): skjerm Fri kontekst mot overflow-kuttet [skip-docs]
Operatoerbeslutning: naar linje-cappen (25) sprekker, skal fri kontekst
overleve i stedet for aa vaere det foerste feltet som forsvinner.
Fri kontekst legges SIST fordi den skal LESES sist. Under et rent head-slice
gjorde nettopp det den til den foerste som falt ut - og det er den ene sloten
brukeren skriver fritt i, som onboarding-agent.md:125 selv kaller den
enkeltkategorien som gjoer raadene mest treffsikre. Posisjon i sammendraget er
en lese-rekkefoelge, ikke en prioritetsrekkefoelge; kuttet blandet de to.
Ved overflow beholdes naa (cap-2) strukturerte felt + fri kontekst + markoer,
altsaa fortsatt noeyaktig cap linjer. Uten fri kontekst er kuttet uendret.
Dette ble den bindende grensen foerst etter a7098e0: med readdir aapnet kan
brukeren legge til filer fritt, saa terskelen paa 26 felt naas naa av
brukerhandling og ikke bare av design.
Verifisert paa den ekte hooken: 40 felt + fri kontekst gir 25 linjer, med
"Fri kontekst" som siste felt og markoeren "(+22 flere felt)" til slutt.
TDD: 2 nye tester, skjermingstesten roed foerst mot forrige commit. Den andre
pinner at overflow UTEN fri kontekst er uendret (back-compat). Suite 1064/1064.
[skip-docs]: ren intern mekanikk - ingen endring i utoverrettet flate.
This commit is contained in:
parent
a7098e0fdf
commit
5a46818dd6
2 changed files with 41 additions and 2 deletions
|
|
@ -234,16 +234,33 @@ export function buildOrgSummary(orgFiles, opts = {}) {
|
|||
// one "Fri kontekst" field regardless of internal markdown structure, so a
|
||||
// plain paragraph is never silently dropped (acceptance K3).
|
||||
const freeContent = orgFiles[FREE_CONTEXT_FILE];
|
||||
let hasFreeContext = false;
|
||||
if (typeof freeContent === 'string' && freeContent.trim()) {
|
||||
const body = collapseProse(freeContent);
|
||||
if (body) fields.push([FREE_CONTEXT_LABEL, body]);
|
||||
if (body) {
|
||||
fields.push([FREE_CONTEXT_LABEL, body]);
|
||||
hasFreeContext = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (fields.length === 0) return '';
|
||||
|
||||
// Budget 1 — lines: over cap, keep (cap-1) fields plus a marker for the rest.
|
||||
//
|
||||
// "Fri kontekst" is exempt from that cut. It is appended LAST so it reads last,
|
||||
// which under a plain head-slice made it the FIRST field to disappear — and it
|
||||
// is the one slot the user writes freely in, which onboarding-agent.md calls
|
||||
// the single category that most sharpens the advice. Position in the summary
|
||||
// is a reading order, not a priority order; the cut must not conflate them.
|
||||
const overflow = fields.length > cap;
|
||||
const kept = overflow ? fields.slice(0, cap - 1) : fields;
|
||||
const room = Math.max(0, cap - 1); // fields emittable alongside the marker
|
||||
let kept = fields;
|
||||
if (overflow) {
|
||||
kept =
|
||||
hasFreeContext && room >= 1
|
||||
? [...fields.slice(0, room - 1), fields[fields.length - 1]]
|
||||
: fields.slice(0, room);
|
||||
}
|
||||
|
||||
// Budget 2 — chars: shared max-min fairly over the fields actually emitted.
|
||||
const allowance = allocateBudget(kept.map(([, value]) => value.length), maxTotalLen);
|
||||
|
|
|
|||
|
|
@ -353,3 +353,25 @@ test('orderOrgFiles — non-.md entries and garbage input are dropped', () => {
|
|||
assert.deepEqual(orderOrgFiles(['notater.txt', '.DS_Store', 'alfa.md']), ['alfa.md']);
|
||||
assert.deepEqual(orderOrgFiles(null), []);
|
||||
});
|
||||
|
||||
test('buildOrgSummary — Fri kontekst survives the overflow cut (it is added last, not least)', () => {
|
||||
const many = Array.from({ length: 40 }, (_, i) => `## Felt${i}\nverdi${i}`).join('\n\n');
|
||||
const s = buildOrgSummary({
|
||||
'organization-profile.md': many,
|
||||
'free-context.md': 'Den ene sloten der brukeren skriver fritt.',
|
||||
});
|
||||
const lines = s.split('\n');
|
||||
assert.ok(lines.length <= 25, `line budget still binds, got ${lines.length}`);
|
||||
assert.match(s, /Fri kontekst: Den ene sloten/, 'free-context must not be the first field dropped');
|
||||
assert.match(lines[lines.length - 1], /flere felt/, 'marker still last');
|
||||
assert.match(lines[lines.length - 2], /^Fri kontekst:/, 'free-context kept as the last field');
|
||||
});
|
||||
|
||||
test('buildOrgSummary — overflow without free-context is unchanged (back-compat)', () => {
|
||||
const many = Array.from({ length: 40 }, (_, i) => `## Felt${i}\nverdi${i}`).join('\n\n');
|
||||
const lines = buildOrgSummary({ 'organization-profile.md': many }, { cap: 10 }).split('\n');
|
||||
assert.equal(lines.length, 10);
|
||||
assert.equal(lines[0], 'Felt0: verdi0');
|
||||
assert.equal(lines[8], 'Felt8: verdi8');
|
||||
assert.match(lines[9], /flere felt/);
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue