refactor(ms-ai-architect): R13 del 1 — nøytraliser Cosmo-personaen i ref-korpusets headinger, etter å ha rettet en gate som var målt usann to ganger

Ordre 20260912T193441Z-7358817909. Steg 1 var ikke transformen, men å rette
roadmapens R13-gate og få den ratifisert. Gaten `grep -rl "Cosmo"
skills/*/references -> 0` var usann på to uavhengige måter:

1. Ordren fanget den første: 451 av forekomstene er Azure Cosmos DB, ekte
   produktinnhold. Diskriminatoren er ikke bokstaven «s» — `Cosmos <norsk
   substantiv>` er genitiv av personaen (`### Cosmos tonalitet`), mens
   `Cosmos DB`/`CosmosClient`/`cosmos_ru` er produkt.
2. Denne økten fant den andre: 132 persona-forekomster ligger i prosa,
   tabeller, dialog-replikker og proveniens-linjer. Heading-nøytralisering
   kan ikke nå dem, så «0 persona» er uoppnåelig også under den ratifiserte
   formen. Operatøren ratifiserte alternativ A: gaten speiler formen, og de
   132 bokføres til R13b/R14.

Tre korreksjoner av premisser som sto i ordren og STATE:
  «ca 320 produkt»   -> 451 (case-sensitivt nett manglet 327 lowercase
                        TOC-ankre + 99 identifikatorer; sann nevner 1 638)
  «169 headinger»    -> 401. 169 var `^## For Cosmo`-prefikset (168) og var
                        internt inkonsistent med sin egen topp-variant (204)
  «417 matcher ingen
   populasjon»       -> 417 er cosmo-headinger utenfor kodefences; briefens
                        nevner var reell hele tiden

Fence-bevissthet er målt skadelig, ikke nødvendig: begge toggle-regler er
gale på dette korpuset (naiv toggle skjuler en ekte heading i
chain-of-thought-prompting.md, CommonMark-regelen ubalanserer
service-level-documentation-dr.md). Fence-agnostisk deteksjon finner 401
heading-linjer i nøyaktig de samme 40 variantene som fence-bevisst finner
400 i — ingen kodeblokk-linje er byte-identisk til en persona-heading. Derfor
nøkles transformen på 40 enumererte heading-tekster og ignorerer fences. En
ukjent variant kaster; en slug-kollisjon kaster. Ingenting auto-fikses.

TOC-en regenereres ikke, den rettes kirurgisk: alle 327 persona-lenker hadde
lenketekst lik én av de 40 heading-tekstene og anker lik slugify av den
(327/327, 0 avvik), så heading og TOC-entry skrives i samme operasjon og
ingen mellomtilstand etterlater en død lenke.

Ratifisert målform: `For Cosmo`, `For Cosmo Skyberg` og `For arkitekten
(Cosmo)` konvergerer på `For arkitekten`. To filer kolliderte og er adjudisert
ved å lese dem, ikke ved regel.

Verifisering (alle 7 kriterier fra ordren):
  G1 persona på heading-linjer   401 -> 0
  G2 døde fragmentlenker         1 -> 1 (pre-eksisterende, unntatt)
  G3 produkt-forekomster         451 -> 451; `Cosmos DB|Azure Cosmos` 308 = 308
  de 3 kun-produkt-filene        byte-identiske
  nettet validert begge veier    injisert persona feller G1; genitiv feller G1;
                                 produkt-heading og de 3 filene passerer
  hele diffen                    802 heading-linjer + 654 TOC-linjer, ANNET = 0
  linjeantall                    728 lagt til = 728 slettet
  suite                          1120/1120 (1097 + 23 nye)
  validate-plugin                250 PASS / 0 FAIL
  stikkprøve                     10 filer, alle 5 skills, inkl. de 3 mest
                                 produkt-tunge (26/20/19) — kun heading+TOC

Utenfor scope, urørt: de 4 SKILL.md, de 23 commands, CLAUDE.md, README.md,
NOTICE.md, docs/ (alt R14).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-12 22:12:28 +02:00
commit 3a73eeafdc
380 changed files with 1711 additions and 729 deletions

5
.gitignore vendored
View file

@ -26,12 +26,15 @@ org/
# hand-authored taxonomy (lag 0), the decision ledger (lag 2), the curated
# AI Act deadline source (RX-REG, sync-tested consumer contract) and the
# adjudicated Layer B allowlist (Enhet A2 — the gate's strictness contract,
# human-reviewed per entry, must survive a fresh clone) are tracked.
# human-reviewed per entry, must survive a fresh clone) and the ratified R13 Cosmo
# persona-gate baseline (the reference numbers check-cosmo-gate.mjs compares against —
# a gate whose baseline is regenerated locally proves nothing) are tracked.
scripts/kb-update/data/*
!scripts/kb-update/data/domain-taxonomy.json
!scripts/kb-update/data/decisions.json
!scripts/kb-update/data/ai-act-deadlines.json
!scripts/kb-update/data/layerb-allowlist.json
!scripts/kb-update/data/cosmo-gate-baseline.json
# Generated skill-lifecycle detection report (Spor B / B1) — regenerated on demand,
# like the kb-update reports above. The detector script + curated inputs are tracked.
scripts/kb-eval/data/skill-lifecycle-report.json

View file

@ -0,0 +1,188 @@
#!/usr/bin/env node
// check-cosmo-gate.mjs — the RATIFIED R13 persona gate (operator 2026-09-12, alt. A).
//
// Replaces the roadmap's `grep -rl "Cosmo" skills/*/references | wc -l -> 0`, which was
// measured false twice over (it would delete 451 Azure Cosmos DB occurrences, and it is
// unreachable under a heading-only scope because 132 persona occurrences live in prose,
// tables and dialogue). Full derivation: lib/cosmo-persona.mjs header.
//
// THREE CLAUSES
// G1 persona occurrences on markdown heading lines in the reference corpus = 0
// G2 every fragment link resolves to a real heading slug, except the anchors on the
// committed exemption list (pre-existing, not caused by R13)
// G3 product occurrences unchanged from the committed baseline, and each product-only
// file still carries zero persona
//
// USAGE
// node scripts/kb-update/check-cosmo-gate.mjs # check (exit 1 on fail)
// node scripts/kb-update/check-cosmo-gate.mjs --emit-baseline # write the baseline JSON
// node scripts/kb-update/check-cosmo-gate.mjs --validate-net # prove the net both ways
//
// --validate-net is not decoration. A gate whose null result has never been forced to
// the other answer is not a measurement (memory decision-gate-must-be-validated-both-
// ways): it injects a known-positive persona heading into a copy of a real corpus file
// and asserts G1 FAILS, then asserts the known-negative product-only files PASS.
import { readFileSync, writeFileSync, existsSync } from 'node:fs';
import { join, dirname, relative } from 'node:path';
import { fileURLToPath } from 'node:url';
import { globSync } from 'node:fs';
import { classifyCosmo, findDeadAnchors } from './lib/cosmo-persona.mjs';
const __dirname = dirname(fileURLToPath(import.meta.url));
const PLUGIN_ROOT = join(__dirname, '..', '..');
const BASELINE_PATH = join(__dirname, 'data', 'cosmo-gate-baseline.json');
/** Every reference file in the corpus, as repo-relative paths, sorted. */
function refFiles() {
return globSync('skills/*/references/**/*.md', { cwd: PLUGIN_ROOT }).sort();
}
/** Measure the whole corpus: persona buckets, product total, per-file detail. */
function measure() {
const files = refFiles();
const totals = { heading: 0, toc: 0, prose: 0, product: 0 };
const headingFiles = new Set();
const perFile = {};
const deadAnchors = [];
for (const rel of files) {
const src = readFileSync(join(PLUGIN_ROOT, rel), 'utf8');
const c = classifyCosmo(src);
totals.heading += c.persona.heading;
totals.toc += c.persona.toc;
totals.prose += c.persona.prose;
totals.product += c.product;
if (c.persona.heading > 0) headingFiles.add(rel);
perFile[rel] = { persona: c.personaTotal, product: c.product };
for (const d of findDeadAnchors(src)) deadAnchors.push(`${rel}#${d.anchor}`);
}
return { files, totals, headingFiles: [...headingFiles].sort(), perFile, deadAnchors };
}
/** Files carrying Azure Cosmos DB but no persona at all — must stay untouched. */
function productOnlyFiles(m) {
return m.files.filter((f) => m.perFile[f].product > 0 && m.perFile[f].persona === 0);
}
function emitBaseline() {
const m = measure();
const pof = productOnlyFiles(m);
const baseline = {
_comment: 'Ratified R13 persona-gate baseline. Measured before the heading transform; '
+ 'G1 drives personaHeadings to 0, G2 and G3 must not move. Regenerate ONLY with a '
+ 'ratified scope change — a silently moved baseline is a gate that proves nothing.',
measured: new Date().toISOString().slice(0, 10),
refFiles: m.files.length,
personaHeadings: m.totals.heading,
personaHeadingFiles: m.headingFiles.length,
personaTocOccurrences: m.totals.toc,
personaProseOccurrences: m.totals.prose,
productOccurrences: m.totals.product,
productOnlyFiles: pof,
productOnlyFileCounts: Object.fromEntries(pof.map((f) => [f, m.perFile[f].product])),
deadAnchorsExempt: m.deadAnchors,
};
writeFileSync(BASELINE_PATH, `${JSON.stringify(baseline, null, 2)}\n`, 'utf8');
console.log(`baseline skrevet: ${relative(PLUGIN_ROOT, BASELINE_PATH)}`);
console.log(JSON.stringify(baseline, null, 2));
}
function check() {
if (!existsSync(BASELINE_PATH)) {
console.error('FEIL: ingen baseline. Kjoer --emit-baseline foer transformen.');
process.exit(2);
}
const b = JSON.parse(readFileSync(BASELINE_PATH, 'utf8'));
const m = measure();
const fails = [];
// --- G1: no persona left on any heading line ---
if (m.totals.heading !== 0) {
fails.push(`G1: ${m.totals.heading} persona-forekomster staar fortsatt paa heading-linjer `
+ `i ${m.headingFiles.length} filer (baseline var ${b.personaHeadings})`);
}
// --- G2: no dead fragment links beyond the committed exemptions ---
const exempt = new Set(b.deadAnchorsExempt);
const newDead = m.deadAnchors.filter((d) => !exempt.has(d));
if (newDead.length) {
fails.push(`G2: ${newDead.length} NYE doede fragmentlenker: ${newDead.slice(0, 10).join(', ')}`);
}
const healed = b.deadAnchorsExempt.filter((d) => !m.deadAnchors.includes(d));
// --- G3: product untouched ---
if (m.totals.product !== b.productOccurrences) {
fails.push(`G3: produkt-forekomster ${m.totals.product} != baseline ${b.productOccurrences} `
+ `(differanse ${m.totals.product - b.productOccurrences})`);
}
for (const [f, n] of Object.entries(b.productOnlyFileCounts)) {
const now = m.perFile[f];
if (!now) { fails.push(`G3: kun-produkt-fila ${f} finnes ikke lenger`); continue; }
if (now.product !== n) fails.push(`G3: ${f} produkt ${now.product} != baseline ${n}`);
if (now.persona !== 0) fails.push(`G3: ${f} har faatt ${now.persona} persona-forekomst(er)`);
}
console.log('=== R13 persona-gate (ratifisert 2026-09-12, alt. A) ===');
console.log(`ref-filer : ${m.files.length} (baseline ${b.refFiles})`);
console.log(`G1 persona paa heading-linjer : ${m.totals.heading} (baseline ${b.personaHeadings})`);
console.log(` persona i TOC-linjer : ${m.totals.toc} (baseline ${b.personaTocOccurrences})`);
console.log(` persona i proesa/tabell : ${m.totals.prose} (baseline ${b.personaProseOccurrences}) `
+ '— UTENFOR R13-scope, bokfoert til R13b/R14');
console.log(`G2 doede fragmentlenker : ${m.deadAnchors.length} `
+ `(${exempt.size} unntatt, ${newDead.length} nye, ${healed.length} forsvunnet)`);
console.log(`G3 produkt-forekomster : ${m.totals.product} (baseline ${b.productOccurrences})`);
console.log(` kun-produkt-filer urørt : ${Object.keys(b.productOnlyFileCounts).length}`);
if (fails.length) {
console.log('\nGATE FAILED');
for (const f of fails) console.log(` x ${f}`);
process.exit(1);
}
console.log('\nGATE PASSED');
}
/** Force the gate to the other answer — a null result nobody could falsify is not one. */
function validateNet() {
const m = measure();
let bad = 0;
// Known-positive: inject a persona heading into a real corpus file's content and
// assert the classifier sees it. If this cannot fail the gate, the gate is blind.
const victim = m.files[0];
const injected = `${readFileSync(join(PLUGIN_ROOT, victim), 'utf8')}\n## For Cosmo\n`;
const ic = classifyCosmo(injected);
const base = classifyCosmo(readFileSync(join(PLUGIN_ROOT, victim), 'utf8'));
if (ic.persona.heading !== base.persona.heading + 1) {
console.log(`x KJENT-POSITIV: injisert "## For Cosmo" ble IKKE sett `
+ `(${base.persona.heading} -> ${ic.persona.heading})`); bad++;
} else {
console.log(`ok KJENT-POSITIV: injisert "## For Cosmo" felte G1 `
+ `(${base.persona.heading} -> ${ic.persona.heading}) i ${victim}`);
}
// Known-positive #2: the Norwegian genitive must also be caught, since it is the
// case the letter-s heuristic gets wrong in BOTH directions.
const gen = classifyCosmo('### Cosmos tonalitet\n');
if (gen.persona.heading !== 1) { console.log('x KJENT-POSITIV: genitiv "### Cosmos tonalitet" ikke sett'); bad++; }
else console.log('ok KJENT-POSITIV: genitiv "### Cosmos tonalitet" felte G1');
// Known-negative: a product heading must NOT trip the gate.
const prod = classifyCosmo('### Azure Cosmos DB for GraphRAG\n');
if (prod.personaTotal !== 0 || prod.product !== 1) {
console.log(`x KJENT-NEGATIV: produkt-heading feilklassifisert `
+ `(persona ${prod.personaTotal}, produkt ${prod.product})`); bad++;
} else console.log('ok KJENT-NEGATIV: "### Azure Cosmos DB for GraphRAG" gir 0 persona, 1 produkt');
// Known-negative #2: the real product-only files must be clean of persona.
for (const f of productOnlyFiles(m)) {
const c = classifyCosmo(readFileSync(join(PLUGIN_ROOT, f), 'utf8'));
if (c.personaTotal !== 0) { console.log(`x KJENT-NEGATIV: ${f} klassifisert med persona`); bad++; }
else console.log(`ok KJENT-NEGATIV: ${f} — 0 persona, ${c.product} produkt`);
}
console.log(bad === 0 ? '\nNETTET VALIDERT BEGGE VEIER' : `\nNETT-VALIDERING FEILET (${bad})`);
process.exit(bad === 0 ? 0 : 1);
}
const arg = process.argv[2];
if (arg === '--emit-baseline') emitBaseline();
else if (arg === '--validate-net') validateNet();
else check();

View file

@ -0,0 +1,23 @@
{
"_comment": "Ratified R13 persona-gate baseline. Measured before the heading transform; G1 drives personaHeadings to 0, G2 and G3 must not move. Regenerate ONLY with a ratified scope change — a silently moved baseline is a gate that proves nothing.",
"measured": "2026-09-12",
"refFiles": 389,
"personaHeadings": 401,
"personaHeadingFiles": 374,
"personaTocOccurrences": 654,
"personaProseOccurrences": 132,
"productOccurrences": 451,
"productOnlyFiles": [
"skills/ms-ai-advisor/references/architecture/decision-trees.md",
"skills/ms-ai-advisor/references/architecture/poc-template.md",
"skills/ms-ai-advisor/references/development/agent-framework.md"
],
"productOnlyFileCounts": {
"skills/ms-ai-advisor/references/architecture/decision-trees.md": 3,
"skills/ms-ai-advisor/references/architecture/poc-template.md": 1,
"skills/ms-ai-advisor/references/development/agent-framework.md": 1
},
"deadAnchorsExempt": [
"skills/ms-ai-advisor/references/development/agent-framework.md#pattern-3-human-in-the-loop"
]
}

View file

@ -0,0 +1,324 @@
// cosmo-persona.mjs — R13 Cosmo del 1: classify a `cosmo` occurrence as PERSONA or
// PRODUCT, and neutralise the persona out of reference-corpus headings (and the TOC
// entries that anchor to them) without touching a single Azure Cosmos DB mention.
//
// WHY THIS LIB EXISTS. The roadmap's R13 acceptance gate
// (.claude/projects/2026-07-02-helhetlig-roadmap § R13) reads
// `grep -rl "Cosmo" skills/*/references | wc -l -> 0`. Measured 2026-09-12 over the
// 389 reference files, that gate is false twice over:
//
// 1. Of 1 638 case-insensitive `cosmo` occurrences, 451 are AZURE COSMOS DB — a real
// Microsoft product, legitimate content in the BCDR / engineering / cost files.
// A gate demanding zero `Cosmo` demands they be deleted. The discriminator is NOT
// the letter s: `Cosmos DB` / `CosmosClient` / `cosmos_ru` are product, while
// `Cosmos <norsk substantiv>` is the persona's GENITIVE (`### Cosmos tonalitet`).
// 2. Of the 1 187 persona occurrences, 132 live in prose, tables, dialogue and
// provenance lines that heading neutralisation cannot reach. "Zero persona" is
// therefore unreachable under the ratified heading-only scope either.
//
// THE RATIFIED GATE (operator 2026-09-12, alternative A) — three clauses, baselines
// measured over skills/*/references:
// G1 persona occurrences on markdown heading lines 401 -> 0 (374 files, 40 variants)
// G2 every fragment link resolves to a real heading unchanged (1 pre-existing dead)
// G3 product occurrences unchanged 451 -> 451
// The 132 residual persona occurrences are booked as an open decision for R13b/R14.
//
// WHY EXACT-STRING KEYING AND NOT FENCE-AWARENESS. Measured: BOTH fence rules are
// wrong on this corpus. A naive ``` toggle (what transform.mjs buildToc uses) leaves
// chain-of-thought-prompting.md unbalanced — 19 markers — and hides the real heading at
// line 403; the CommonMark "a closing fence carries no info string" rule instead
// unbalances service-level-documentation-dr.md, whose ```markdown blocks contain
// ```mermaid / ```bash examples as literal content. Measured resolution: fence-agnostic
// detection finds 401 heading-like persona lines in EXACTLY the same 40 variants that
// fence-aware detection finds 400 in — i.e. no code-block line in the corpus is
// byte-identical to a persona heading, so fence state cannot change the verdict. The
// transform therefore keys on the 40 enumerated heading texts and ignores fences. That
// is both correct here and auditable: every rewrite is a table entry a human ratified.
//
// ARCHITECTURE INVARIANT: this lib NEVER writes and never guesses. An unmapped persona
// heading throws; an in-file slug collision throws. Applying content is the driver's
// job (neutralize-cosmo-headings.mjs), behind the operator gate.
// Function words that may follow a bare product mention of "Cosmos" in prose, e.g.
// "Redis for hot, Cosmos for warm data" / "autoscale for Cosmos i DR-region". A
// genitive persona use is always "Cosmos <substantiv>", never "Cosmos <funksjonsord>".
// Enumerated rather than inferred: the net is validated by running it over all 1 638
// occurrences and hand-checking every bare-Cosmos line (25 of them).
const PRODUCT_FOLLOWERS = [
'for', 'og', 'eller', 'i', 'med', 'til', 'som', 'er', 'ellers', 'via',
'på', 'pa', 'av', 'fra', 'ved', 'kan', 'skal', 'hvis', 'men', 'the', 'to',
];
/**
* Is the `cosmo` occurrence at the START of `text` the persona (not the product)?
*
* PERSONA /cosmo(?!s)/i 1 178 measured (851 `Cosmo`,
* 327 lowercase TOC anchors)
* `Cosmos <lowercase substantiv>` 9 measured (Norwegian genitive)
* PRODUCT everything else 451 measured
*
* @param {string} text the document text from the occurrence's first character on
* @returns {boolean}
*/
export function isPersonaOccurrence(text) {
const s = String(text ?? '');
// `Cosmo`, `Cosmo's`, `Cosmo-tilnærming`, and the lowercase `#...-cosmo)` anchors.
if (/^cosmo(?!s)/i.test(s)) return true;
// Norwegian genitive: capital `Cosmos` + space + a lowercase noun. A capital follower
// (DB, PITR, L2, Kusto, Snowflake) or no space at all (`Cosmos;`, `Cosmos-DB`,
// `CosmosClient`) is product, as is a lowercase function word.
const gen = /^Cosmos[ \t]+(\S+)/.exec(s);
if (!gen) return false;
const follower = gen[1];
if (!/^[a-zæøå]/.test(follower)) return false;
const word = follower.replace(/[^\p{L}]/gu, '').toLowerCase();
return word !== '' && !PRODUCT_FOLLOWERS.includes(word);
}
/** Does this line carry at least one persona occurrence? */
function hasPersona(line) {
for (const m of String(line).matchAll(/cosmo/gi)) {
if (isPersonaOccurrence(String(line).slice(m.index))) return true;
}
return false;
}
/**
* GitHub-style heading slug. MIRRORS transform.mjs slugify (lowercase, drop all
* punctuation, spaces hyphens, Unicode-aware so æ/ø/å survive) kept local rather
* than imported so this lib stays dependency-free, and pinned to parity by
* test-cosmo-persona's slug cases against known corpus anchors.
* @param {string} heading
* @returns {string}
*/
export function slugifyHeading(heading) {
return String(heading ?? '')
.toLowerCase()
.replace(/[^\p{L}\p{N}\s_-]/gu, '')
.trim()
.replace(/\s/g, '-');
}
/**
* Count every `cosmo` occurrence, bucketing the persona ones by where they sit.
* The buckets are what make the ratified scope legible: `heading` + `toc` is what R13
* neutralises, `prose` is the 132 booked for R13b/R14, `product` is what G3 protects.
*
* @param {string} content
* @returns {{persona: {heading: number, toc: number, prose: number},
* personaTotal: number, product: number, total: number}}
*/
export function classifyCosmo(content) {
const persona = { heading: 0, toc: 0, prose: 0 };
let product = 0;
for (const line of String(content ?? '').split('\n')) {
const isHeading = /^#{1,6}\s+/.test(line);
// Spans covered by a markdown fragment link `[text](#anchor)` — both the visible
// link text and the anchor sit inside one span, which is why a TOC entry for a
// persona heading contributes two occurrences.
const linkSpans = [...line.matchAll(/\[[^\]]*\]\(#[^)]*\)/g)]
.map((m) => [m.index, m.index + m[0].length]);
for (const m of line.matchAll(/cosmo/gi)) {
if (!isPersonaOccurrence(line.slice(m.index))) { product++; continue; }
if (isHeading) persona.heading++;
else if (linkSpans.some(([a, b]) => m.index >= a && m.index < b)) persona.toc++;
else persona.prose++;
}
}
const personaTotal = persona.heading + persona.toc + persona.prose;
return { persona, personaTotal, product, total: personaTotal + product };
}
/**
* The ratified rewrite table: all 40 persona heading variants measured in
* the reference corpus on 2026-09-12, keyed by heading text (the line without its `#`
* prefix) neutral text. Operator-ratified 2026-09-12: `For Cosmo`,
* `For Cosmo Skyberg` and `For arkitekten (Cosmo)` all converge on `For arkitekten`,
* giving the corpus ONE heading vocabulary where it had three.
*
* No target introduces a word its source did not carry, except the two sanctioned
* substitutions for the persona token `arkitekten` (the role Cosmo played) and `å`
* (where the name was the clause's subject). Pinned by test-cosmo-persona.
*/
export const HEADING_MAP = {
// --- the four bulk variants (363 of 401 occurrences) ---
'For arkitekten (Cosmo)': 'For arkitekten',
'For Cosmo': 'For arkitekten',
'For Cosmo Skyberg': 'For arkitekten',
'For Cosmo: Beslutningsveiledning': 'Beslutningsveiledning',
// --- the tail: 36 variants, 1-2 occurrences each ---
'Oppsummering for Cosmo': 'Oppsummering',
'10. For Cosmo: Modellvalgveiledning': '10. Modellvalgveiledning',
'Key insights for Cosmo': 'Key insights',
'Architecture decision prompts for Cosmo': 'Architecture decision prompts',
'Røde flagg (når skal Cosmo advare?)': 'Røde flagg (når skal arkitekten advare?)',
'Fallgruver (Cosmo Har Sett Før)': 'Fallgruver',
"Desicion Matrix (Cosmo's Cheat Sheet)": 'Desicion Matrix',
"Shortcut Design Patterns (Cosmo's Checklist)": 'Shortcut Design Patterns',
'For Cosmo — Beslutningsveiledning': 'Beslutningsveiledning',
'Praktiske anbefalinger for arkitekten (Cosmo)': 'Praktiske anbefalinger for arkitekten',
'For arkitekten (Cosmo) — spørsmål, fallgruver og anbefalinger':
'For arkitekten — spørsmål, fallgruver og anbefalinger',
'For Cosmo — når bruker denne kunnskapen?': 'For arkitekten — når bruker denne kunnskapen?',
'For Cosmo: Quick Reference Card': 'Quick Reference Card',
"Cosmo's Talking Points": 'Talking Points',
'Når skal Cosmo foreslå Impact Assessment?': 'Når skal arkitekten foreslå Impact Assessment?',
'Cosmos veiledningsstrategi': 'Veiledningsstrategi',
'Cosmos spørsmål for å utdype': 'Spørsmål for å utdype',
'Red flags Cosmo skal varsle om': 'Red flags arkitekten skal varsle om',
'Cosmos tonalitet': 'Tonalitet',
'Cosmos sjekkliste før avslutning': 'Sjekkliste før avslutning',
"Cosmo's quick decision tree": 'Quick decision tree',
"Cosmo's Stakeholder Communication Checklist": 'Stakeholder Communication Checklist',
'Cosmo-tilnærming': 'Tilnærming',
'Decision trees for Cosmo': 'Decision trees',
'Red flags for Cosmo å se etter': 'Red flags å se etter',
'For Cosmo Skyberg: Application Insights for LLM Monitoring':
'Application Insights for LLM Monitoring',
'For Cosmo: Anvendelse i Arkitekturrådgivning': 'Anvendelse i Arkitekturrådgivning',
'For Arkitekten (Cosmo)': 'For Arkitekten',
"Cosmo's Quick Decision Matrix": 'Quick Decision Matrix',
'Cosmos anbefalinger': 'Anbefalinger',
'For Cosmo: Practical Implementation': 'Practical Implementation',
'For Cosmo: Veiledning i Arkitekturdialog': 'Veiledning i Arkitekturdialog',
'10. Anbefalinger for Cosmo Skyberg': '10. Anbefalinger',
'For Cosmo: Anvendelse i Microsoft AI-arkitektur': 'Anvendelse i Microsoft AI-arkitektur',
'Cosmo-oppsummering': 'Oppsummering',
'Spørsmål Cosmo bør stille kunden': 'Spørsmål å stille kunden',
};
/**
* Per-file overrides where the shared table would collide inside one document. Measured
* by sweeping the ratified mapping over all 389 files and collecting every slug that
* would end up shared: exactly TWO, both adjudicated by reading the file.
*
* 1. feedback-loops-continuous-improvement.md carries both `## For arkitekten (Cosmo)`
* (L674) and `## For Cosmo` (L745), which the ratified mapping would fold onto one
* slug. The second section's own body names the alternative the brief already
* sanctions "Nøkkelpunkter å fremheve i konsultasjon"
* (docs/cosmo-removal-brief-2026-06.md:24) so the target is read off the content
* rather than invented.
* 2. application-insights-llm-monitoring.md's `## For Cosmo Skyberg: Application
* Insights for LLM Monitoring` (L717) would collide with the document's own H1 title
* (L1), because the heading's suffix merely restated that title. Dropping the suffix
* loses nothing and lands on the ratified `For arkitekten` vocabulary.
*/
export const FILE_HEADING_OVERRIDES = {
'skills/ms-ai-engineering/references/mlops-genaiops/feedback-loops-continuous-improvement.md': {
'For Cosmo': 'Nøkkelpunkter for rådgivning',
},
'skills/ms-ai-governance/references/monitoring-observability/application-insights-llm-monitoring.md': {
'For Cosmo Skyberg: Application Insights for LLM Monitoring': 'For arkitekten',
},
};
/**
* Every fragment link whose anchor matches no heading slug in the same document.
* Heading collection is fence-agnostic, matching the transform see the header note.
*
* @param {string} content
* @returns {Array<{text: string, anchor: string}>}
*/
export function findDeadAnchors(content) {
const src = String(content ?? '');
const slugs = new Set();
for (const line of src.split('\n')) {
const m = /^#{1,6}\s+(.+?)\s*$/.exec(line);
if (m) slugs.add(slugifyHeading(m[1].trim()));
}
const dead = [];
for (const m of src.matchAll(/\[([^\]]*)\]\(#([^)]*)\)/g)) {
if (!slugs.has(m[2])) dead.push({ text: m[1], anchor: m[2] });
}
return dead;
}
/**
* Neutralise the persona out of this document's headings, and rewrite the TOC entries
* that anchor to them in the SAME operation so no step of the run ever leaves a dead
* fragment link. Pure: returns new content, writes nothing.
*
* Surgical by design. The TOC is NOT regenerated (buildToc would reorder entries,
* re-derive every anchor and drop `###` entries); only the persona entries are
* rewritten, in place, leaving all 2 709 non-persona fragment links byte-identical.
* Measured precondition that makes this exact: all 327 persona TOC links carry a link
* text that is one of the 40 heading texts AND an anchor equal to slugify of it
* (327/327, zero deviations).
*
* Throws never writes a guess when:
* - a heading carries persona but is not in HEADING_MAP (an unmeasured variant)
* - a rewrite would make two headings in this file share one slug
* - a persona fragment link's anchor is not slugify of its own link text
*
* Idempotent: neutral content has no persona headings left to match.
*
* @param {string} content
* @param {{relPath?: string}} [opts] relPath selects FILE_HEADING_OVERRIDES
* @returns {{content: string, changes: Array<{kind: string, line: number, from: string, to: string}>}}
*/
export function neutralizeContent(content, { relPath = '' } = {}) {
const src = String(content ?? '');
const overrides = FILE_HEADING_OVERRIDES[relPath] || {};
const target = (text) => (Object.prototype.hasOwnProperty.call(overrides, text)
? overrides[text]
: HEADING_MAP[text]);
const lines = src.split('\n');
const changes = [];
// --- pass 1: headings ---
const rewritten = lines.map((line, i) => {
const m = /^(#{1,6})(\s+)(.+?)(\s*)$/.exec(line);
if (!m || !hasPersona(line)) return line;
const from = m[3];
const to = target(from);
if (to === undefined) {
throw new Error(`ukjent persona-heading i ${relPath || '<ukjent fil>'}:${i + 1}: "${from}"`);
}
changes.push({ kind: 'heading', line: i + 1, from, to });
return `${m[1]}${m[2]}${to}${m[4]}`;
});
// --- collision check, BEFORE any TOC work: would two headings share one slug? ---
const slugCount = new Map();
for (const line of rewritten) {
const m = /^#{1,6}\s+(.+?)\s*$/.exec(line);
if (!m) continue;
const s = slugifyHeading(m[1].trim());
slugCount.set(s, (slugCount.get(s) || 0) + 1);
}
for (const c of changes) {
const s = slugifyHeading(c.to);
if (slugCount.get(s) > 1) {
throw new Error(
`slug-kollisjon i ${relPath || '<ukjent fil>'}:${c.line}: "${c.from}" -> "${c.to}" `
+ `gir slug "#${s}" som alt finnes i fila. Krever en FILE_HEADING_OVERRIDES-entry.`,
);
}
}
// --- pass 2: the TOC entries anchoring to the headings we just renamed ---
const out = rewritten.map((line, i) => line.replace(
/\[([^\]]*)\]\(#([^)]*)\)/g,
(whole, text, anchor) => {
if (!hasPersona(whole)) return whole;
const to = target(text);
if (to === undefined) {
throw new Error(
`persona-fragmentlenke som ikke peker paa en kjent heading, `
+ `${relPath || '<ukjent fil>'}:${i + 1}: "${whole}"`,
);
}
if (anchor !== slugifyHeading(text)) {
throw new Error(
`anker matcher ikke slugify(lenketekst) i ${relPath || '<ukjent fil>'}:${i + 1}: `
+ `"${whole}" — forventet "#${slugifyHeading(text)}"`,
);
}
changes.push({ kind: 'toc', line: i + 1, from: text, to });
return `[${to}](#${slugifyHeading(to)})`;
},
));
return { content: out.join('\n'), changes };
}

View file

@ -0,0 +1,117 @@
#!/usr/bin/env node
// neutralize-cosmo-headings.mjs — R13 Cosmo del 1: apply the ratified heading
// neutralisation across the reference corpus, rewriting each persona heading and the TOC
// entries anchored to it in ONE per-file operation, so no intermediate state leaves a
// dead fragment link.
//
// SCOPE (operator-ratified 2026-09-12, alternative A). In: the 401 persona headings in
// 374 reference files (40 measured variants) plus the 327 TOC entries that anchor to
// them. OUT: the 4 SKILL.md files, the 23 commands, CLAUDE.md / README.md / NOTICE.md,
// the docs/ files (all R14), and the 132 persona occurrences in prose, tables, dialogue
// and provenance lines — those need editorial judgement, not a scripted transform, and
// are booked as an open decision for R13b/R14.
//
// INVARIANTS asserted per file BEFORE any write (a throw aborts the whole run and
// writes nothing — the plan-then-write discipline of strip-stale-verified-pipe.mjs):
// - zero persona occurrences remain on heading lines
// - product occurrence count byte-for-byte unchanged (the 451 Azure Cosmos DB mentions)
// - line count unchanged (headings are edited in place, never added or removed)
// - no NEW dead fragment link
// - only heading lines and TOC-entry lines differ from the original
// Idempotent: a re-run finds no persona heading and is a no-op, so an interrupted run is
// recovered by re-running.
//
// Usage: node scripts/kb-update/neutralize-cosmo-headings.mjs [--dry]
import { readFileSync, realpathSync, globSync } from 'node:fs';
import { join, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import { atomicWriteSync } from './lib/atomic-write.mjs';
import { classifyCosmo, findDeadAnchors, neutralizeContent } from './lib/cosmo-persona.mjs';
const __dirname = dirname(fileURLToPath(import.meta.url));
const PLUGIN_ROOT = join(__dirname, '..', '..');
/**
* Assert every per-file invariant. Throws on the first violation so the run aborts
* before a single byte is written.
*/
function assertInvariant(rel, before, after, changes) {
const b = classifyCosmo(before);
const a = classifyCosmo(after);
if (a.persona.heading !== 0) {
throw new Error(`${rel}: ${a.persona.heading} persona-forekomst(er) staar igjen paa heading-linjer`);
}
if (a.product !== b.product) {
throw new Error(`${rel}: produkt-forekomster endret ${b.product} -> ${a.product}`);
}
const lb = before.split('\n').length;
const la = after.split('\n').length;
if (lb !== la) throw new Error(`${rel}: linjeantall endret ${lb} -> ${la}`);
const deadBefore = new Set(findDeadAnchors(before).map((d) => d.anchor));
const newDead = findDeadAnchors(after).map((d) => d.anchor).filter((x) => !deadBefore.has(x));
if (newDead.length) throw new Error(`${rel}: nye doede ankre: ${newDead.join(', ')}`);
// Only the lines the transform claims to have touched may differ.
const touched = new Set(changes.map((c) => c.line));
const lbArr = before.split('\n');
const laArr = after.split('\n');
for (let i = 0; i < lbArr.length; i++) {
if (lbArr[i] === laArr[i]) continue;
if (!touched.has(i + 1)) {
throw new Error(`${rel}:${i + 1}: linje endret uten aa staa i endringslista\n`
+ ` foer: ${lbArr[i]}\n etter: ${laArr[i]}`);
}
}
}
function main() {
const dry = process.argv.includes('--dry');
const files = globSync('skills/*/references/**/*.md', { cwd: PLUGIN_ROOT }).sort();
const planned = [];
const skipped = [];
let headingChanges = 0;
let tocChanges = 0;
for (const rel of files) {
const abs = join(PLUGIN_ROOT, rel);
const before = readFileSync(abs, 'utf8');
const { content: after, changes } = neutralizeContent(before, { relPath: rel });
if (after === before) { skipped.push(rel); continue; }
assertInvariant(rel, before, after, changes);
headingChanges += changes.filter((c) => c.kind === 'heading').length;
tocChanges += changes.filter((c) => c.kind === 'toc').length;
planned.push({ rel, out: after, changes });
}
console.log(`ref-filer: ${files.length} | aa endre: ${planned.length} | urørt: ${skipped.length}`);
console.log(`heading-endringer: ${headingChanges} | TOC-endringer: ${tocChanges}`);
if (dry) {
console.log('\n(dry run — ingen skriving)');
const byTarget = new Map();
for (const p of planned) {
for (const c of p.changes.filter((x) => x.kind === 'heading')) {
const k = `${c.from} -> ${c.to}`;
byTarget.set(k, (byTarget.get(k) || 0) + 1);
}
}
console.log('\n--- heading-mapping som vil brukes ---');
for (const [k, v] of [...byTarget.entries()].sort((x, y) => y[1] - x[1])) {
console.log(`${String(v).padStart(4)} ${k}`);
}
return;
}
for (const p of planned) atomicWriteSync(join(PLUGIN_ROOT, p.rel), p.out);
console.log(`\nSkrev ${planned.length} filer.`);
}
const isMain = (() => {
try {
return realpathSync(process.argv[1]) === realpathSync(fileURLToPath(import.meta.url));
} catch {
return false;
}
})();
if (isMain) main();

View file

@ -1066,7 +1066,7 @@ Ikke alle AI-tiltak krever en fullstendig utredning. Bruk denne guiden for å be
---
## For Cosmo Skyberg
## For arkitekten
Denne malen er ditt hovedverktøy for strukturerte utredninger. Slik bruker du den:

View file

@ -285,7 +285,7 @@ Bruk denne sjekklisten **etter** at alternativanalysen er ferdig for å verifise
---
## For Cosmo Skyberg
## For arkitekten
Denne referansefilen er ditt verktøy for strukturert alternativsammenligning. Slik bruker du den:

View file

@ -282,7 +282,7 @@ MVP (Minimum Viable Product) for AI-prosjekter har to dimensjoner:
---
## For Cosmo Skyberg
## For arkitekten
Denne referansefilen hjelper deg å vurdere om et prosjekt faktisk er gjennomførbart — ikke bare om teknologien er riktig. Bruk den slik:

View file

@ -378,7 +378,7 @@ Disse mønstrene kan kombineres med ethvert nivå og er ikke del av den lineære
---
## For arkitekten (Cosmo)
## For arkitekten
### Spørsmål for å plassere kunden på riktig nivå

View file

@ -223,7 +223,7 @@ Add MCP servers to your Claude Code settings file at `~/.claude/settings.json` o
---
## For Cosmo
## For arkitekten
These MCP servers enhance the 7-phase architect workflow:

View file

@ -258,7 +258,7 @@ Når en tjeneste ikke er tilgjengelig i Norway East:
---
## For Cosmo Skyberg
## For arkitekten
Denne referansefilen er ditt verktøy for å sikre at arkitekturforslag faktisk er gjennomførbare i riktig Azure-region. Slik bruker du den:

View file

@ -221,7 +221,7 @@ Identifisert (A) → Prioritert (P1/P2/P3) → Validering pågår (🔄) → Val
---
## For Cosmo Skyberg
## For arkitekten
Denne referansefilen er ditt verktøy for å sikre transparens og etterprøvbarhet i arkitekturvurderinger. Slik bruker du den:

View file

@ -415,7 +415,7 @@ Backend mottar POST med verb + data, returnerer oppdatert card.
---
## For arkitekten (Cosmo)
## For arkitekten
### Anbefalinger ved arkitektursamtaler

View file

@ -385,7 +385,7 @@ Get-MgBetaReportMicrosoft365CopilotUserCountSummary `
- E3: 90 dager gratis → nok for de fleste compliance-behov
- E5: 1 år retention → kun nødvendig for sensitive sektorer (finans, helse)
## For arkitekten (Cosmo)
## For arkitekten
### Spørsmål å stille kunden

View file

@ -407,7 +407,7 @@ while True:
---
## For arkitekten (Cosmo)
## For arkitekten
### Når anbefale hvilken løsning?

View file

@ -502,7 +502,7 @@ Ingen item quota (ingen indeksering), men:
- Bruk "maker-provided credentials" for å unngå per-user auth
- Kombiner flere API-kall i én action (reduser round-trips)
## For arkitekten (Cosmo)
## For arkitekten
### Spørsmål å stille

View file

@ -449,7 +449,7 @@ transferToAgent(essentialVariables);
---
## For arkitekten (Cosmo)
## For arkitekten
### Når foreslå context window optimization?

View file

@ -236,7 +236,7 @@ New-DLPComplianceRule -Name "Block Highly Confidential and Personal" `
| Sette "Non-business" som default data group | Nye connectors blokkeres automatisk | Vurder "Business" som default, eller bruk explicit allow-listing |
| Glemme å koordinere Purview og Power Platform DLP | Policy conflicts, agents feiler | Lag felles governance-dokument, synkroniser policies |
### Røde flagg (når skal Cosmo advare?)
### Røde flagg (når skal arkitekten advare?)
1. **Organisasjonen har ingen sensitivity labels:** DLP for labels fungerer ikke uten merkede data
2. **DLP policies opprettes uten simulation mode:** Høy risiko for produksjonsfeil
@ -378,7 +378,7 @@ Copilot DLP og governance er designet etter Zero Trust-prinsipper:
- **Med DLP:** Forebyggende kostnadseffektivt vs. bøter
- **Breakeven:** Hvis DLP forhindrer ett databrudd (snittkostnad: 10M NOK i Norge), er E5-lisensiering betalt i ett år
## For arkitekten (Cosmo)
## For arkitekten
### Spørsmål å stille kunden

View file

@ -590,7 +590,7 @@ Descriptor:
---
## For arkitekten (Cosmo)
## For arkitekten
### Når anbefale hvilken security pattern?

View file

@ -351,7 +351,7 @@ Triage: "Jeg ser du har spørsmål om barnetrygd.
| Administrere agents | M365 admin (gratis med tenant) |
| Custom engine agents | Azure subscription for hosting |
## For arkitekten (Cosmo)
## For arkitekten
### Spørsmål å stille kunden

View file

@ -437,7 +437,7 @@ For advanced scenarios kan du deploye custom model fra Microsoft Foundry og bruk
- Opprett "shared prompts" i Copilot Studio Tools (ikke topic-level)
- Reduserer duplikasjon og vedlikehold
## For arkitekten (Cosmo)
## For arkitekten
### Spørsmål å stille kunden

View file

@ -472,7 +472,7 @@ Agent kan detektere brukerens språk i hver melding og bytte språk dynamisk gje
---
## For arkitekten (Cosmo)
## For arkitekten
### Når kunden spør om flerspråklig støtte

View file

@ -430,7 +430,7 @@ Agenter kan konfigureres til å detektere brukerens språk og respondere på sam
---
## For arkitekten (Cosmo)
## For arkitekten
### Når anbefale hver modell

View file

@ -297,7 +297,7 @@ Topics og trigger phrases kan defineres per språk:
---
## For arkitekten (Cosmo)
## For arkitekten
### Designprinsipper for Topics

View file

@ -414,7 +414,7 @@ Custom engine agents krever **egen hosting** — dette er den største kostnadsf
---
## For arkitekten (Cosmo)
## For arkitekten
### Når anbefale custom engine agents?

View file

@ -420,7 +420,7 @@ namespace ITSupportAgent {
---
## For arkitekten (Cosmo)
## For arkitekten
### Assessment Framework

View file

@ -364,7 +364,7 @@ Work IQ (semantic search) krever **minst én Microsoft 365 Copilot-lisens** i te
---
## For arkitekten (Cosmo)
## For arkitekten
### Spørsmål å stille kunden

View file

@ -722,9 +722,9 @@ DLP Policy: Block data movement outside EU
---
## For arkitekten (Cosmo)
## For arkitekten
### Key insights for Cosmo
### Key insights
1. **Governance er ikke bare policy enforcement — det er enablement:**
- Zoned governance strategy gir citizen developers frihet i Zone 1 mens IT beholder kontroll i Zone 2/3
@ -773,7 +773,7 @@ DLP Policy: Block data movement outside EU
- **Problem:** Technical debt, retrofitting governance er vanskeligere enn upfront design
- **Solution:** Pilot with governance fra dag 1 — test governance i liten skala før scale-out
### Architecture decision prompts for Cosmo
### Architecture decision prompts
**Når kunde sier "Vi vil ha Copilot agents", spør:**
1. "Hvilke zones trenger dere? Skal alle bygge agents (Zone 1) eller kun IT-godkjente makers (Zone 2/3)?"

View file

@ -340,7 +340,7 @@ Hvis plugin brukes til å fatte avgjørelser som påvirker individers rettighete
3. **Leverage Graph connector for read-only scenarios:** Billigere enn custom engine agents (ingen hosting cost)
4. **Microsoft 365 Agents Toolkit over Copilot Studio:** Toolkit er gratis, Copilot Studio krever Power Platform-lisens for produksjon
## For arkitekten (Cosmo)
## For arkitekten
### Spørsmål å stille kunden

View file

@ -377,7 +377,7 @@ Trenger du "write once, run anywhere" for flere agenter?
---
## For arkitekten (Cosmo)
## For arkitekten
### Spørsmål å stille i rådgivningen

View file

@ -401,7 +401,7 @@ Trenger du å berike Copilot med ekstern data?
---
## For arkitekten (Cosmo)
## For arkitekten
### Anbefalinger

View file

@ -445,7 +445,7 @@ Scenario: 100 brukere, 1000 flow runs/måned via Copilot Studio agent
---
## For arkitekten (Cosmo)
## For arkitekten
### Når anbefale Power Automate + Copilot Studio?

View file

@ -267,7 +267,7 @@ SharePoint Copilot Agents respekterer **eksisterende SharePoint-permissions og s
---
## For arkitekten (Cosmo)
## For arkitekten
### Spørsmål å stille kunden

View file

@ -353,7 +353,7 @@ Chat-historikk i Teams/Copilot er underlagt arkiveringskrav for offentlig sektor
---
## For arkitekten (Cosmo)
## For arkitekten
### Spørsmål å stille kunden

View file

@ -334,7 +334,7 @@ Microsoft.CognitiveServices/account (kind: AIServices)
---
## For Cosmo: Beslutningsveiledning
## Beslutningsveiledning
### Når anbefale Foundry
1. Multi-model behov (OpenAI + DeepSeek + Grok + Llama)

View file

@ -605,7 +605,7 @@ Copilot Studio kan bruke **Bring Your Own Model** fra Microsoft Foundry for cust
| **Prompt assistant** | GA | Utkast til prompts raskere med GPT-modell-forslag i Prompt builder |
| **Tilgjengelighetsretningslinjer for Adaptive Cards** | GA | Støtte for skjermlesere, tastaturnavigasjon og Teams-spesifikke scenarier |
## For Cosmo: Beslutningsveiledning
## Beslutningsveiledning
### Når anbefale Copilot Studio

View file

@ -548,7 +548,7 @@ Blokkerer Copilot fra å svare når prompts inneholder sensitiv data som:
---
## For Cosmo: Beslutningsveiledning
## Beslutningsveiledning
### Når anbefale M365 Copilot

View file

@ -337,7 +337,7 @@ Bred dekning via Global Standard/Provisioned (GPT-5-familien, GPT-4.1, o-serien,
---
## 10. For Cosmo: Modellvalgveiledning
## 10. Modellvalgveiledning
### Beslutningsflyt

View file

@ -534,7 +534,7 @@ Action: Flagg for jurist-gjennomgang
---
## For Cosmo: Beslutningsveiledning
## Beslutningsveiledning
### Når anbefale Power Platform AI

View file

@ -586,7 +586,7 @@ Pricing not publicly disclosed — contact Microsoft for quote
---
## For arkitekten (Cosmo)
## For arkitekten
### Når anbefale adversarial testing?

View file

@ -400,7 +400,7 @@ Chain-of-thought øker token-forbruk betydelig:
---
## For arkitekten (Cosmo)
## For arkitekten
### 5-8 spørsmål å stille kunden

View file

@ -506,7 +506,7 @@ Basert på testing (Azure OpenAI dokumentasjon):
---
## For arkitekten (Cosmo)
## For arkitekten
### Når anbefale domain-specific prompting?

View file

@ -540,7 +540,7 @@ result = evaluate(
---
## For arkitekten (Cosmo)
## For arkitekten
### Spørsmål å stille kunden

View file

@ -419,7 +419,7 @@ Few-shot (10 eksempler): 1000-3000 tokens
---
## For arkitekten (Cosmo)
## For arkitekten
### Når anbefale Few-Shot

View file

@ -368,7 +368,7 @@ Function calling påvirker kostnaden på flere måter:
**Viktig:** Azure OpenAI krever godkjenning (application form). Offentlig sektor i Norge har vanligvis raskere godkjenning.
## For arkitekten (Cosmo)
## For arkitekten
### Spørsmål å stille kunden

View file

@ -406,7 +406,7 @@ Sources:
---
## For arkitekten (Cosmo)
## For arkitekten
### Spørsmål å stille kunden

View file

@ -517,7 +517,7 @@ var sessionId = $"{userId}_{Guid.NewGuid()}";
---
## For arkitekten (Cosmo)
## For arkitekten
### Confidence markers

View file

@ -411,7 +411,7 @@ Can you tell me what the image depicts?
| Batch-prosessering (asynkront) | 50% rabatt (Azure OpenAI batch API) | Latency 24t |
| Cache responses (semantic cache) | Varierer | Treff-rate avhengig |
## For arkitekten (Cosmo)
## For arkitekten
### Discovery-spørsmål

View file

@ -949,7 +949,7 @@ def grade(sample: dict, item: dict) -> float:
---
## For arkitekten (Cosmo)
## For arkitekten
### Når foreslå Microsoft Foundry Evaluation?

View file

@ -416,7 +416,7 @@ Deployment C: Chatbot (variabel prompt, medium output)
---
## For arkitekten (Cosmo)
## For arkitekten
### Når anbefale Realtime API

View file

@ -429,7 +429,7 @@ Reasoning models krever:
- `o1`, `o3-mini`, `o4-mini`, `codex-mini`
- `gpt-5-mini`, `gpt-5-nano`, `gpt-5.1-chat`, `gpt-5.1-codex-mini`
## For arkitekten (Cosmo)
## For arkitekten
### Spørsmål å stille kunden

View file

@ -735,7 +735,7 @@ Kritisk: Compliance-features koster minimalt, men gir juridisk trygghet
---
## For arkitekten (Cosmo)
## For arkitekten
### Strategiske Vurderinger

View file

@ -517,7 +517,7 @@ System messages teller som **input tokens** i hver API-call. Lengre personas = h
---
## For arkitekten (Cosmo)
## For arkitekten
### Når anbefale Role-Playing Personas

View file

@ -346,7 +346,7 @@ Krever Azure OpenAI-ressurs med støttet modell (se over). Ingen spesiell lisens
---
## For arkitekten (Cosmo)
## For arkitekten
### Spørsmål å stille kunden

View file

@ -294,7 +294,7 @@ System messages teller mot totale input-tokens for hver request. For repetitive
---
## For arkitekten (Cosmo)
## For arkitekten
### Design-anbefalinger
1. **Start med rollespesifikasjon:** Definer alltid "You are..." først. Dette gir modellen en persona å forholde seg til.

View file

@ -445,7 +445,7 @@ Generation parameters er **tilgjengelige på alle Azure OpenAI-lisenser** (ingen
---
## For arkitekten (Cosmo)
## For arkitekten
### Når bruke hvilke parametere

View file

@ -505,7 +505,7 @@ Break-even requests/måned: $1,224 / $0.00036 = 3.4M requests
---
## For arkitekten (Cosmo)
## For arkitekten
### Praktiske spørsmål under arkitekturrådgivning

View file

@ -17,7 +17,7 @@
- [Integrasjon med Microsoft-stakken](#integrasjon-med-microsoft-stakken)
- [Offentlig sektor (Norge)](#offentlig-sektor-norge)
- [Kostnad og lisensiering](#kostnad-og-lisensiering)
- [For arkitekten (Cosmo)](#for-arkitekten-cosmo)
- [For arkitekten](#for-arkitekten)
- [Kilder og verifisering](#kilder-og-verifisering)
## Introduksjon
@ -332,7 +332,7 @@ New-MgIdentityGovernanceLifecycleWorkflow -BodyParameter $params
**Verified (Microsoft Learn + Baseline pricing knowledge, 2026-02)**
## For arkitekten (Cosmo)
## For arkitekten
### Spørsmål å stille kunden

View file

@ -17,7 +17,7 @@
- [Integrasjon med Microsoft-stakken](#integrasjon-med-microsoft-stakken)
- [Offentlig sektor (Norge)](#offentlig-sektor-norge)
- [Kostnad og lisensiering](#kostnad-og-lisensiering)
- [For arkitekten (Cosmo)](#for-arkitekten-cosmo)
- [For arkitekten](#for-arkitekten)
- [Kilder og verifisering](#kilder-og-verifisering)
## Introduksjon
@ -332,7 +332,7 @@ workflow = (
**Microsoft Foundry:** Pay-as-you-go (consumption-based), ingen upfront lisens
**Copilot Studio:** Inkludert i Microsoft 365 Copilot lisens (18 000 NOK/user/år), eller standalone (~2000 NOK/user/år)
## For arkitekten (Cosmo)
## For arkitekten
### Spørsmål å stille klienten

View file

@ -18,7 +18,7 @@
- [Compliance Reporting](#compliance-reporting)
- [Norsk offentlig sektor](#norsk-offentlig-sektor)
- [Beslutningsrammeverk](#beslutningsrammeverk)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -443,7 +443,7 @@ class NorwegianPublicSectorCompliance:
| Sensitiv data-agent | Immutable storage + strengere access control | Personvern og sikkerhet |
| Multi-agent system | Distribuert tracing + sentralisert audit | Etterprøvbarhet på tvers av agenter |
## For Cosmo
## For arkitekten
- **Audit logging er ikke valgfritt** -- det er et regulatorisk krav under EU AI Act Art. 12 og norsk forvaltningsrett. Implementer fra dag 1, ikke som etterpåklok.
- **Beslutningskjeden er det viktigste** -- logg ikke bare hva agenten svarte, men HVORFOR: hvilken intent ble klassifisert, hvilken agent ble valgt, hvilke data ble hentet, hvilken modell ble brukt.

View file

@ -19,7 +19,7 @@
- [Foundry Control Plane Kostnadsoptimalisering](#foundry-control-plane-kostnadsoptimalisering)
- [Norsk offentlig sektor](#norsk-offentlig-sektor)
- [Beslutningsrammeverk](#beslutningsrammeverk)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -391,7 +391,7 @@ budget_alert_config = {
| Budsjettsensitiv organisasjon | Model Router + strenge token-grenser | Automatisk kostnadsoptimalisering |
| Multi-avdelings deployment | Cost attribution med tagging | Sporbar kostnadsfordeling |
## For Cosmo
## For arkitekten
- **Model tiering er den viktigste optimaliseringen** -- bruk gpt-4.1-nano/mini for routing og klassifisering, og reserver gpt-4o for kompleks resonnering. Typisk 30-50% kostnadsreduksjon.
- **Model Router** i Microsoft Foundry er det enkleste tiltaket -- det ruter automatisk enkle forespørsler til billigere modeller uten kodeendringer.

View file

@ -19,7 +19,7 @@
- [Governance for Agent Ecosystems](#governance-for-agent-ecosystems)
- [Norsk offentlig sektor](#norsk-offentlig-sektor)
- [Beslutningsrammeverk](#beslutningsrammeverk)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -440,7 +440,7 @@ Visjon: Deling av agenter mellom offentlige virksomheter
| Offentlig sektor fellesløsning | Organizational catalog + Digdir-koordinering | Gjenbruk på tvers av virksomheter |
| Multi-agent økosystem internt | Custom plugin registry + Copilot integration | Skalerbar oppdagelse og governance |
## For Cosmo
## For arkitekten
- **Agenter er apps i Microsoft 365** -- bruk den unified app-modellen for distribusjon, governance og oppdagelse. Ikke bygg parallelle distribusjonskanaler.
- **Agent manifest er kontrakten** mellom agent og plattform -- definer kapabiliteter, autorisasjonskrav og støttede kanaler eksplisitt. Dette muliggjør automatisert oppdagelse og governance.

View file

@ -17,7 +17,7 @@
- [Integrasjon med Microsoft-stakken](#integrasjon-med-microsoft-stakken)
- [Offentlig sektor (Norge)](#offentlig-sektor-norge)
- [Kostnad og lisensiering](#kostnad-og-lisensiering)
- [For arkitekten (Cosmo)](#for-arkitekten-cosmo)
- [For arkitekten](#for-arkitekten)
- [Kilder og verifisering](#kilder-og-verifisering)
## Introduksjon
@ -414,7 +414,7 @@ results = mlflow.genai.evaluate(
| **Azure OpenAI** | Pay-as-you-go (per token) | Azure OpenAI access (申请 required) |
| **Application Insights** | Pay-as-you-go (per GB ingested) | Azure subscription |
## For arkitekten (Cosmo)
## For arkitekten
### Spørsmål å stille under arkitekturgjennomgang

View file

@ -18,7 +18,7 @@
- [Implementeringsmønstre](#implementeringsmønstre)
- [Norsk offentlig sektor](#norsk-offentlig-sektor)
- [Beslutningsrammeverk](#beslutningsrammeverk)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -316,7 +316,7 @@ class RAGFeedbackCollector:
| Agent med fallende kvalitet | Øk til 50% sampling + aktivér alle evaluatorer | Rask diagnose av rotårsak |
| Post-modellbytte | 100% evaluering i 7 dager | Verifiser at ny modell opprettholder kvalitet |
## For Cosmo
## For arkitekten
- **Continuous evaluation er ikke valgfritt** -- det er en forutsetning for produksjonsdeployment. Implementer Microsoft Foundry evaluatorer fra dag 1 med sampling tilpasset risikoprofilen.
- **Closed-loop feedback** er gullstandarden: identifiser problemer via monitoring, diagnostiser med MLflow traces, forbedre prompts/RAG, valider med evalueringssett, og deploy gradvis.

View file

@ -20,7 +20,7 @@
- [Model Selection for Latency](#model-selection-for-latency)
- [Norsk offentlig sektor](#norsk-offentlig-sektor)
- [Beslutningsrammeverk](#beslutningsrammeverk)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -398,7 +398,7 @@ async def select_model_for_task(task_type: str, context: dict) -> str:
| RAG med store dokumenter | Prompt caching + chunk-optimalisering | Reduser TTFT for store prompts |
| Global distribusjon | APIM multi-region + Front Door | Nearest-region routing |
## For Cosmo
## For arkitekten
- **Streaming er alltid-på for interaktive agenter** -- det er den enkelttiltaket som mest forbedrer brukeropplevelsen, selv om total tid forblir lik.
- **Model tiering er obligatorisk** for kostnadseffektiv latency-optimalisering -- bruk nano/mini for routing og klassifisering, gpt-4o for kompleks resonnering.

View file

@ -17,7 +17,7 @@
- [Integrasjon med Microsoft-stakken](#integrasjon-med-microsoft-stakken)
- [Offentlig sektor (Norge)](#offentlig-sektor-norge)
- [Kostnad og lisensiering](#kostnad-og-lisensiering)
- [For arkitekten (Cosmo)](#for-arkitekten-cosmo)
- [For arkitekten](#for-arkitekten)
- [Kilder og verifisering](#kilder-og-verifisering)
## Introduksjon
@ -399,7 +399,7 @@ Gir data lineage tracking og governance-enforcement.
---
## For arkitekten (Cosmo)
## For arkitekten
### Spørsmål å stille klienten

View file

@ -19,7 +19,7 @@
- [Observability SDK Integration](#observability-sdk-integration)
- [Norsk offentlig sektor](#norsk-offentlig-sektor)
- [Beslutningsrammeverk](#beslutningsrammeverk)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -368,7 +368,7 @@ span.set_attribute("query.text", redactor.redact(query))
| Produksjon høy-risiko | 100% tracing + Sentinel + Agent 365 | Full compliance og sikkerhet |
| Multi-team organisasjon | Agent 365 + sentralisert Log Analytics | Unified governance på tvers av team |
## For Cosmo
## For arkitekten
- **OpenTelemetry-basert tracing er fundamentet** -- all agent-observability bygger på traces med spans. Implementer fra dag 1, ikke legg til etterpå.
- **Agent 365** er veien fremover for enterprise-scale agent governance -- det gir unified synlighet på tvers av Copilot Studio, Foundry og tredjepartsagenter.

View file

@ -19,7 +19,7 @@
- [Specialization Hierarchies](#specialization-hierarchies)
- [Norsk offentlig sektor](#norsk-offentlig-sektor)
- [Beslutningsrammeverk](#beslutningsrammeverk)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -409,7 +409,7 @@ KOMMUNE_AGENT_MAP = {
| Sensitive domener med compliance | Handoff med human-in-the-loop | Sikkerhet + etterprøvbarhet |
| Dynamisk agentøkosystem | Capability advertisement + discovery | Agenter kan registreres/fjernes uten kodeendring |
## For Cosmo
## For arkitekten
- **Handoff-mønsteret** i Semantic Kernel er den mest naturlige routing-mekanismen for multi-agent-systemer -- triage-agenten klassifiserer og delegerer, spesialistene behandler.
- **Kombiner LLM-basert og deterministisk routing** for best resultat: Bruk CLU for kjente intenter med høy volum, LLM for edge cases og nye scenarier.

View file

@ -19,7 +19,7 @@
- [Red Teaming](#red-teaming)
- [Norsk offentlig sektor](#norsk-offentlig-sektor)
- [Beslutningsrammeverk](#beslutningsrammeverk)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -394,7 +394,7 @@ attack_scenarios = [
| Produksjons-agenter | Kvartalsvis red teaming + continuous monitoring | Proaktiv sikkerhetsposisjon |
| Offentlig sektor | Full STRIDE + NSM-alignment + EU AI Act compliance | Regulatorisk krav |
## For Cosmo
## For arkitekten
- **Defense-in-depth er obligatorisk** for agenter -- ingen enkeltkontroll stopper alle angrep. Implementer Prompt Shields, safety meta-prompts, verktøy-sandboxing OG continuous monitoring.
- **Prompt injection er trussel #1** for agentsystemer. Azure AI Content Safety Prompt Shields er den viktigste tekniske kontrollen -- integrer den tidlig i agentpipelinen, ALLTID før data sendes til modellen.

View file

@ -19,7 +19,7 @@
- [Sikkerhet](#sikkerhet)
- [Multi-vendor Interoperabilitet](#multi-vendor-interoperabilitet)
- [Norsk Offentlig Sektor](#norsk-offentlig-sektor)
- [For Cosmo — Beslutningsveiledning](#for-cosmo--beslutningsveiledning)
- [Beslutningsveiledning](#beslutningsveiledning)
- [Arkitekturmønster](#arkitekturmønster)
- [Installasjon og SDK-er](#installasjon-og-sdk-er)
- [Kilder og verifisering](#kilder-og-verifisering)
@ -505,7 +505,7 @@ logger.LogInformation(
---
## For Cosmo — Beslutningsveiledning
## Beslutningsveiledning
### Når skal du anbefale A2A?

View file

@ -17,7 +17,7 @@
- [Integrasjon med Microsoft-stakken](#integrasjon-med-microsoft-stakken)
- [Offentlig sektor (Norge)](#offentlig-sektor-norge)
- [Kostnad og lisensiering](#kostnad-og-lisensiering)
- [For arkitekten (Cosmo)](#for-arkitekten-cosmo)
- [For arkitekten](#for-arkitekten)
- [Kilder og verifisering](#kilder-og-verifisering)
## Introduksjon
@ -452,7 +452,7 @@ logger.LogInformation(
3. **Async over sync** → Bruk Service Bus for non-realtime workflows (billigere enn Azure Functions)
4. **Shared compute** → Kjør flere lightweight agents på samme App Service
## For arkitekten (Cosmo)
## For arkitekten
### Spørsmål å stille

View file

@ -17,7 +17,7 @@
- [Integrasjon med Microsoft-stakken](#integrasjon-med-microsoft-stakken)
- [Offentlig sektor (Norge)](#offentlig-sektor-norge)
- [Kostnad og lisensiering](#kostnad-og-lisensiering)
- [For arkitekten (Cosmo)](#for-arkitekten-cosmo)
- [For arkitekten](#for-arkitekten)
- [Kilder og verifisering](#kilder-og-verifisering)
## Introduksjon
@ -513,7 +513,7 @@ Autonomous workflows bør følge **Digdir Referansearkitektur for datautveksling
| **Consumption** | ~0.0003 NOK per action | Variable workloads |
| **Standard** | Fra ~2 500 NOK/mnd | VNet, longer execution time (90 dager) |
## For arkitekten (Cosmo)
## For arkitekten
### Spørsmål å stille kunden

View file

@ -22,7 +22,7 @@
- [CUA vs RPA — Sammenligning](#cua-vs-rpa--sammenligning)
- [Status og tilgjengelighet](#status-og-tilgjengelighet)
- [Norsk offentlig sektor — Relevans](#norsk-offentlig-sektor--relevans)
- [For Cosmo: Beslutningsveiledning](#for-cosmo-beslutningsveiledning)
- [Beslutningsveiledning](#beslutningsveiledning)
- [Kostnadsestimat](#kostnadsestimat)
- [Kilder og verifisering](#kilder-og-verifisering)
@ -403,7 +403,7 @@ CUA-systemer som bidrar til saksbehandling kan klassifiseres som **høyrisiko-AI
---
## For Cosmo: Beslutningsveiledning
## Beslutningsveiledning
### Når anbefale CUA

View file

@ -19,7 +19,7 @@
- [Declarative vs Custom Engine Integration](#declarative-vs-custom-engine-integration)
- [Norsk offentlig sektor](#norsk-offentlig-sektor)
- [Beslutningsrammeverk](#beslutningsrammeverk)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -363,7 +363,7 @@ class CopilotSessionManager:
| ISV-løsning for flere kunder | Commercial Marketplace-publisering | Bred distribusjon, M365 integrasjon |
| Intern pilot med eksisterende data | Declarative agent med SharePoint-kunnskap | Utnytter eksisterende infrastruktur |
## For Cosmo
## For arkitekten
- **Declarative agents er startpunktet** for de fleste M365-integrerte scenarier -- de arver Copilots orkestrator, compliance og distribusjon. Gå til custom engine kun ved reelle begrensninger.
- **CopilotStudioAgent i Semantic Kernel** er broen mellom Copilot-verdenen og programmatisk agent-orkestrering -- bruk den for å inkludere Copilot Studio-agenter i multi-agent-systemer.

View file

@ -18,7 +18,7 @@
- [Skill Abstraction Levels](#skill-abstraction-levels)
- [Norsk offentlig sektor](#norsk-offentlig-sektor)
- [Beslutningsrammeverk](#beslutningsrammeverk)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -327,7 +327,7 @@ Beslutningstre:
| Regulatorisk rapportering | Code-first | Custom validering og compliance-krav |
| Pilot/POC | Declarative | Valider behov før investering i kode |
## For Cosmo
## For arkitekten
- **Start alltid deklarativt** med mindre kravene eksplisitt tilsier noe annet -- det er raskere, billigere og lettere å iterere. Konverter til code-first kun ved reelle begrensninger.
- **Hybrid er normalstilstanden** for enterprise -- enkle agenter i Copilot Studio, komplekse i Semantic Kernel. Design arkitekturen for at begge kan sameksistere.

View file

@ -30,7 +30,7 @@
- [Regional tilgjengelighet](#regional-tilgjengelighet)
- [Enterprise-sikkerhet og governance](#enterprise-sikkerhet-og-governance)
- [Offentlig sektor (Norge)](#offentlig-sektor-norge)
- [For Cosmo: Beslutningsveiledning](#for-cosmo-beslutningsveiledning)
- [Beslutningsveiledning](#beslutningsveiledning)
- [Grenser og kvoter](#grenser-og-kvoter)
- [Kilder og verifisering](#kilder-og-verifisering)
@ -401,7 +401,7 @@ Agenter som bidrar til vedtaksprosesser **må**:
2. Muliggjøre manuell overstyring via human-in-the-loop i workflow
3. Vedlegge agent-konversasjonshistorikk som saksgrunnlag
## For Cosmo: Beslutningsveiledning
## Beslutningsveiledning
### Velg Foundry Agent Service når

View file

@ -21,7 +21,7 @@
- [Deployment: API-endepunkter, Versjonering og A/B-testing](#deployment-api-endepunkter-versjonering-og-ab-testing)
- [Overvåking: Tracing, Tokenbruk og Latensmetrikker](#overvåking-tracing-tokenbruk-og-latensmetrikker)
- [Norsk offentlig sektor](#norsk-offentlig-sektor)
- [For Cosmo: Beslutningsveiledning](#for-cosmo-beslutningsveiledning)
- [Beslutningsveiledning](#beslutningsveiledning)
- [Kilder og verifisering](#kilder-og-verifisering)
## Introduksjon
@ -514,7 +514,7 @@ Foundry Workflows' visuelle designer gir offentlig sektor-organisasjoner en unik
---
## For Cosmo: Beslutningsveiledning
## Beslutningsveiledning
### Spørsmål å stille kunden

View file

@ -17,7 +17,7 @@
- [Integrasjon med Microsoft-stakken](#integrasjon-med-microsoft-stakken)
- [Offentlig sektor (Norge)](#offentlig-sektor-norge)
- [Kostnad og lisensiering](#kostnad-og-lisensiering)
- [For arkitekten (Cosmo)](#for-arkitekten-cosmo)
- [For arkitekten](#for-arkitekten)
- [Kilder og verifisering](#kilder-og-verifisering)
## Introduksjon
@ -575,7 +575,7 @@ scope.RecordOutputMessages(new[] { output });
- Concurrent (4 agenter parallelt) ≈ **$0.04 per run** (samme, men raskere wall-clock)
- Group Chat (5 iterations × 3 agenter × 1000 tokens) ≈ **$0.15 per run**
## For arkitekten (Cosmo)
## For arkitekten
### Spørsmål å stille

View file

@ -19,7 +19,7 @@
- [Resource Quotas](#resource-quotas)
- [Norsk offentlig sektor](#norsk-offentlig-sektor)
- [Beslutningsrammeverk](#beslutningsrammeverk)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -369,7 +369,7 @@ For de fleste offentlige virksomheter i Norge anbefales **hybrid modell**:
| Skjermingsverdig informasjon | Full fysisk isolasjon | Regulatorisk krav, ingen kompromisser |
| Multi-region med data residency | Deployment stamps per region | Datasuverenitet per jurisdiksjon |
## For Cosmo
## For arkitekten
- **Velg isolasjonsmodell basert på dataklassifisering** -- ikke overengineer for åpne data, men underestimer aldri kravene for sensitiv informasjon. Hybrid er vanligvis riktig svar.
- **Tenant-filter i RAG er obligatorisk** -- aldri stol på at agentens instruksjoner alene hindrer datalekkasje. Implementer tekniske kontroller (OData-filter, partition keys) som ikke kan omgås.

View file

@ -19,7 +19,7 @@
- [Integrasjon med Microsoft-stacken](#integrasjon-med-microsoft-stacken)
- [Offentlig sektor (Norge)](#offentlig-sektor-norge)
- [Kostnad og Lisensiering](#kostnad-og-lisensiering)
- [For arkitekten (Cosmo)](#for-arkitekten-cosmo)
- [For arkitekten](#for-arkitekten)
- [Kilder og verifisering](#kilder-og-verifisering)
## Introduksjon
@ -421,7 +421,7 @@ Kernel agentKernel = sharedKernel.Clone(); // Rebruk AI service connections
**Offentlig sektor**: Ingen spesielle lisensbegrensninger, men vurder data residency-krav ved valg av AI service (Azure OpenAI vs. OpenAI).
## For arkitekten (Cosmo)
## For arkitekten
### Spørsmål å stille kunden

View file

@ -17,7 +17,7 @@
- [Integrasjon med Microsoft-stakken](#integrasjon-med-microsoft-stakken)
- [Offentlig sektor (Norge)](#offentlig-sektor-norge)
- [Kostnad og lisensiering](#kostnad-og-lisensiering)
- [For arkitekten (Cosmo)](#for-arkitekten-cosmo)
- [For arkitekten](#for-arkitekten)
- [Kilder og verifisering](#kilder-og-verifisering)
## Introduksjon
@ -424,7 +424,7 @@ def update_citizen_record(ssn: str, field: str, value: str) -> str:
---
## For arkitekten (Cosmo)
## For arkitekten
### Spørsmål å stille klienten

View file

@ -19,7 +19,7 @@
- [Policy-pipeline for AI Gateway](#policy-pipeline-for-ai-gateway)
- [Relevante referansearkitekturer](#relevante-referansearkitekturer)
- [Hensyn for norsk offentlig sektor](#hensyn-for-norsk-offentlig-sektor)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -403,7 +403,7 @@ En komplett AI gateway-policy kombinerer flere policies i riktig rekkefølge:
---
## For Cosmo
## For arkitekten
- APIM som AI Gateway er den anbefalte PaaS-tilnærmingen for organisasjoner som trenger sentralisert styring over Azure OpenAI og andre LLM-backends -- spesielt relevant for offentlig sektor med krav til kostnadsfordeling og compliance.
- De fem hovdkapabilitetene (token limiting, load balancing, circuit breaker, semantic caching, content safety) dekker de fleste enterprise-behov uten egenutviklet kode.

View file

@ -18,7 +18,7 @@
- [API Key Rotation](#api-key-rotation)
- [Defense-in-Depth Mønster](#defense-in-depth-mønster)
- [Referanser](#referanser)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -411,7 +411,7 @@ Kombiner klient-autentisering (OAuth) med backend-autentisering (managed identit
---
## For Cosmo
## For arkitekten
- **Bruk denne referansen** når kunder trenger veiledning om autentisering og autorisering av AI-APIer gjennom APIM, spesielt ved overgang fra API-nøkler til managed identity.
- Anbefal alltid managed identity som primær autentiseringsmetode mot Azure OpenAI — det eliminerer nøkkelhåndtering og reduserer angrepsflaten.

View file

@ -20,7 +20,7 @@
- [Geografisk ruting](#geografisk-ruting)
- [Kostnadsestimat for Front Door + APIM](#kostnadsestimat-for-front-door--apim)
- [Referanser](#referanser)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -433,7 +433,7 @@ Merk: Front Door Standard er rimeligere (~60% av Premium-pris) men mangler Priva
- [Check header policy](https://learn.microsoft.com/en-us/azure/api-management/check-header-policy) -- header-validering
- [Architecture best practices for Azure Front Door](https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-front-door) -- Well-Architected-anbefalinger
## For Cosmo
## For arkitekten
- **Bruk denne referansen** nar kunden trenger global distribusjon av AI-tjenester, ekstra DDoS-beskyttelse, eller WAF foran AI-gateway-en sin.
- For de fleste norske offentlige virksomheter er Front Door overkill for rene interne AI-tjenester. Anbefal det primaert for innbyggerrettede tjenester med hoy trafikk eller behov for geographic redundancy.

View file

@ -22,7 +22,7 @@
- [Hybrid-tilnærminger](#hybrid-tilnærminger)
- [Well-Architected Framework Perspektiv](#well-architected-framework-perspektiv)
- [Referanser](#referanser)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -408,7 +408,7 @@ APIM bør alltid brukes i følgende scenarier:
---
## For Cosmo
## For arkitekten
- **Bruk denne referansen** når kunder spør om de trenger APIM eller kan koble direkte til Azure OpenAI. Beslutningsmatrisen gir et strukturert svar.
- Tommelfingerregel: Hvis kunden har mer enn én applikasjon ELLER strenge sikkerhetskrav (som offentlig sektor typisk har) → anbefal APIM.

View file

@ -19,7 +19,7 @@
- [Pool Metrics](#pool-metrics)
- [Best Practices](#best-practices)
- [Referanser](#referanser)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -515,7 +515,7 @@ resource backendHealthAlert 'Microsoft.Insights/metricAlerts@2018-03-01' = {
---
## For Cosmo
## For arkitekten
- **Bruk denne referansen** når kunder trenger å sette opp load balancing mellom flere Azure OpenAI-instanser via APIM, spesielt for PTU + Standard fallback-mønstre.
- Anbefal alltid circuit breaker med `acceptRetryAfter: true` for Azure OpenAI backends — dette er kritisk for å håndtere 429 throttling uten å overbelaste backend.

View file

@ -18,7 +18,7 @@
- [Kostnadsbesparelsesanalyse](#kostnadsbesparelsesanalyse)
- [Caching-tjenester: Intern vs. Ekstern](#caching-tjenester-intern-vs-ekstern)
- [Referanser](#referanser)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -413,7 +413,7 @@ Opprett en dedikert operasjon for administratorer:
- [Set up an external cache in Azure API Management](https://learn.microsoft.com/en-us/azure/api-management/api-management-howto-cache-external) -- Redis-oppsett
- [Application design for AI workloads - Caching strategies](https://learn.microsoft.com/en-us/azure/well-architected/ai/application-design#implement-multi-layer-caching-strategies) -- Well-Architected-anbefalinger
## For Cosmo
## For arkitekten
- **Bruk denne referansen** nar kunden onsker a redusere AI-kostnader gjennom caching, eller nar de trenger a forbedre responstider for brukere som stiller lignende sporsmol.
- Start med `score-threshold="0.15"` for semantisk caching -- dette gir god balanse. Juster ned til 0.10 for hoyere hit rate i FAQ-scenarier, eller opp til 0.25 for mer presise matcher i kritiske applikasjoner.

View file

@ -19,7 +19,7 @@
- [Avanserte mønstre](#avanserte-mønstre)
- [Anti-mønstre](#anti-mønstre)
- [Komplett resiliens-policy](#komplett-resiliens-policy)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -515,7 +515,7 @@ Kombiner circuit breaker med aktiv health checking:
---
## For Cosmo
## For arkitekten
- Circuit breaker er obligatorisk for alle Azure OpenAI backends i produksjon -- uten det risikerer du cascading failures og bortkastet gateway-kapasitet mot throttlede backends.
- Sett ALLTID `acceptRetryAfter: true` for Azure OpenAI backends. Azure OpenAI returnerer presise Retry-After verdier som gir optimal recovery-timing. Uten dette bruker du den statiske tripDuration som kan være for kort eller for lang.

View file

@ -20,7 +20,7 @@
- [Custom Metrics](#custom-metrics)
- [FinOps Integrasjon](#finops-integrasjon)
- [Referanser](#referanser)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -454,7 +454,7 @@ Kombiner APIM-metriker med Azure resource tags for helhetlig kostnadsbilde:
---
## For Cosmo
## For arkitekten
- **Bruk denne referansen** når kunder trenger å implementere kostnadssporing og intern fakturering for AI-tjenester gjennom APIM.
- Start med `llm-emit-token-metric` policy med Department- og CostCenter-dimensjoner — dette gir umiddelbar synlighet i token-bruk per avdeling.

View file

@ -20,7 +20,7 @@
- [Selvbetjeningsarbeidsflyt for brukere](#selvbetjeningsarbeidsflyt-for-brukere)
- [Azure API Center: Komplementaer katalog](#azure-api-center-komplementaer-katalog)
- [Referanser](#referanser)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -374,7 +374,7 @@ For storre organisasjoner kan Azure API Center brukes sammen med APIM Developer
- [API Management subscriptions](https://learn.microsoft.com/en-us/azure/api-management/api-management-subscriptions) -- abonnementshondtering
- [Self-host the developer portal](https://learn.microsoft.com/en-us/azure/api-management/developer-portal-self-host) -- self-hosting
## For Cosmo
## For arkitekten
- **Bruk denne referansen** nar kunden onsker a gjore AI-API-er tilgjengelige for interne eller eksterne utviklere med selvbetjening, dokumentasjon og tilgangskontroll.
- For norsk offentlig sektor, anbefal alltid Microsoft Entra ID (Azure AD) som identity provider for Developer Portal -- unnga brukernavn/passord-registrering for bedre sikkerhet og sentral brukerstyring.

View file

@ -19,7 +19,7 @@
- [Komplett GenAI Policy Stack](#komplett-genai-policy-stack)
- [GenAI Policy Referanse](#genai-policy-referanse)
- [Referanser](#referanser)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -639,7 +639,7 @@ Outbound (fra topp til bunn):
---
## For Cosmo
## For arkitekten
- **Bruk denne referansen** når kunder trenger å implementere AI safety og governance gjennom APIM-policyer, spesielt content safety, prompt-validering og audit-logging.
- Den viktigste policyen for norsk offentlig sektor er `llm-content-safety` med `shield-prompt="true"` — dette blokkerer jailbreak-forsøk og uønsket innhold FØR det når modellen.

View file

@ -18,7 +18,7 @@
- [Throttling og Retry-håndtering](#throttling-og-retry-håndtering)
- [Komplett Bicep-eksempel](#komplett-bicep-eksempel)
- [Overvåking og feilsøking](#overvåking-og-feilsøking)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -640,7 +640,7 @@ ApiManagementGatewayLogs
---
## For Cosmo
## For arkitekten
- Priority-based load balancing med PTU som Priority 1 og PAYGO som Priority 2 er det anbefalte mønsteret for enterprise AI-arkitekturer -- det maksimerer utnyttelsen av forhåndskjøpt kapasitet og faller automatisk tilbake til pay-per-use ved behov.
- Backend pools er approksimerte: ulike gateway-instanser synkroniserer ikke, så vektede fordelinger er omtrentlige. For AI-workloads er dette akseptabelt fordi Azure OpenAI selv håndterer throttling med 429/Retry-After.

View file

@ -19,7 +19,7 @@
- [Eksport til Microsoft Foundry for modellevaluering](#eksport-til-microsoft-foundry-for-modellevaluering)
- [Personvern og compliance](#personvern-og-compliance)
- [Referanser](#referanser)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -443,7 +443,7 @@ LLM-logger kan eksporteres som datasett for modellevaluering i Microsoft Foundry
- [ApiManagementGatewayLlmLog table](https://learn.microsoft.com/en-us/azure/azure-monitor/reference/tables/apimanagementgatewayllmlog) -- Log Analytics-tabellreferanse
- [Monitor AI agents with Application Insights](https://learn.microsoft.com/en-us/azure/azure-monitor/app/agents-view) -- AI-agent-overvaking
## For Cosmo
## For arkitekten
- **Bruk denne referansen** nar kunden trenger a sette opp logging, dashboard eller kostnadsrapportering for sine AI-API-er, eller nar de ma oppfylle compliance-krav rundt sporbarhet av AI-bruk.
- Anbefal alltid a aktivere bade Application Insights (sanntidsmetrikker) og diagnostic settings (Log Analytics for langtidsanalyse) -- de utfyller hverandre.

View file

@ -20,7 +20,7 @@
- [Cross-Region Failover](#cross-region-failover)
- [Nettverksarkitektur](#nettverksarkitektur)
- [Referanser](#referanser)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -443,7 +443,7 @@ Hver region krever eget VNet med nødvendige NSG-regler:
---
## For Cosmo
## For arkitekten
- **Bruk denne referansen** når kunder trenger en AI-gateway som dekker flere Azure-regioner, eller når data residency og failover er sentrale krav.
- For norsk offentlig sektor: Anbefal alltid EØS-regioner (West Europe, North Europe, Sweden Central) og advar eksplisitt mot Global Standard deployments som kan prosessere data utenfor EØS.

View file

@ -19,7 +19,7 @@
- [Policy Fragments for Reuse](#policy-fragments-for-reuse)
- [Bicep: Oppsett av transformasjons-API](#bicep-oppsett-av-transformasjons-api)
- [Referanser](#referanser)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -579,7 +579,7 @@ resource chatOperation 'Microsoft.ApiManagement/service/apis/operations@2023-09-
- [Policy fragments in API Management](https://learn.microsoft.com/en-us/azure/api-management/policy-fragments) -- gjenbrukbare policy-fragmenter
- [Tutorial: Transform and protect your API](https://learn.microsoft.com/en-us/azure/api-management/transform-api) -- hands-on tutorial
## For Cosmo
## For arkitekten
- **Bruk denne referansen** nar kunden onsker a bygge et model-agnostisk AI-API-lag som abstraherer bort leverandoravhengigheter, eller nar de trenger a standardisere feilhandtering pa tvers av AI-backends.
- Anbefal alltid policy fragments for transformasjonslogikk som gjenbrukes pa tvers av flere API-er -- dette reduserer vedlikeholdsbyrden betydelig.

View file

@ -18,7 +18,7 @@
- [Revisjonssporing og audit trail](#revisjonssporing-og-audit-trail)
- [Sikkerhetssjekksliste for AI Gateway](#sikkerhetssjekksliste-for-ai-gateway)
- [Referanser](#referanser)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -536,7 +536,7 @@ ApiManagementGatewayLlmLog
- [Protect enterprise AI with Prompt Shield](https://learn.microsoft.com/en-us/entra/global-secure-access/how-to-ai-prompt-shield) -- Prompt Shields
- [Security planning for LLM-based applications](https://learn.microsoft.com/en-us/ai/playbook/technology-guidance/generative-ai/mlops-in-openai/security/security-plan-llm-application) -- sikkerhetsplanlegging
## For Cosmo
## For arkitekten
- **Bruk denne referansen** nar kunden trenger a herde sin AI gateway for produksjon, oppfylle compliance-krav, eller etablere et forsvar-i-dybden for AI-tjenester.
- For norsk offentlig sektor er P0-kontrollene i sjekklisten obligatoriske. Start alltid med Microsoft Entra ID, IP-filtrering, rate limiting og Content Safety -- disse gir den storste sikkerhetseffekten med lavest implementeringskostnad.

View file

@ -21,7 +21,7 @@
- [Verifisering og feilsøking](#verifisering-og-feilsøking)
- [Komplett policy for semantic caching](#komplett-policy-for-semantic-caching)
- [Tier-kompatibilitet](#tier-kompatibilitet)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -589,7 +589,7 @@ ApiManagementGatewayLogs
---
## For Cosmo
## For arkitekten
- Semantic caching er den mest kostnadseffektive optimaliseringen for AI-workloads med repeterende spørsmål. Start med `score-threshold="0.15"` og juster basert på cache hit rate og brukerfeedback. For FAQ/kundeservice-scenarier, vurder 0.20 for høyere hit rate.
- Krav: Azure Managed Redis med RediSearch-modul (MÅ aktiveres ved opprettelse, kan ikke legges til etterpå) + Azure OpenAI Embeddings deployment. Planlegg disse ressursene fra starten.

View file

@ -22,7 +22,7 @@
- [Token-telling for Streaming](#token-telling-for-streaming)
- [Komplett Streaming-policy](#komplett-streaming-policy)
- [Referanser](#referanser)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -529,7 +529,7 @@ For ikke-streaming requests, bruk standard `llm-emit-token-metric` i outbound:
---
## For Cosmo
## For arkitekten
- **Bruk denne referansen** når kunder implementerer chat-applikasjoner eller AI-assistenter gjennom APIM og trenger streaming-støtte.
- Den absolutt viktigste innstillingen er `buffer-response="false"` i `forward-request`. Uten dette bufres hele SSE-responsen og leveres som én stor blob — som dreper brukeropplevelsen.

View file

@ -21,7 +21,7 @@
- [Monitorering av token-forbruk](#monitorering-av-token-forbruk)
- [Tier-kompatibilitet](#tier-kompatibilitet)
- [Best Practices](#best-practices)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -451,7 +451,7 @@ customMetrics
---
## For Cosmo
## For arkitekten
- Token rate limiting er den viktigste AI gateway-policyen -- alltid start her når du setter opp APIM for Azure OpenAI. Bruk `llm-token-limit` som standard, med `estimate-prompt-tokens="true"` for tidlig avvisning.
- Counter-key-strategien bestemmer granulariteten: subscription-basert for team-nivå, custom headers for etat/prosjekt, JWT claims for bruker-nivå. For offentlig sektor anbefales subscription per team + custom header for kostnadsrapportering.

View file

@ -20,7 +20,7 @@
- [Revisjonsstyring for ikke-brytende endringer](#revisjonsstyring-for-ikke-brytende-endringer)
- [Handtering av brytende endringer](#handtering-av-brytende-endringer)
- [Referanser](#referanser)
- [For Cosmo](#for-cosmo)
- [For arkitekten](#for-arkitekten)
## Introduksjon
@ -386,7 +386,7 @@ info:
- [OWASP: Improper inventory management](https://learn.microsoft.com/en-us/azure/api-management/mitigate-owasp-api-threats#improper-inventory-management) -- sikkerhetsanbefalinger
- [AI gateway in Azure API Management](https://learn.microsoft.com/en-us/azure/api-management/genai-gateway-capabilities) -- AI gateway-oversikt
## For Cosmo
## For arkitekten
- **Bruk denne referansen** nar kunden planlegger versjonering av sine AI-API-er, trenger a migrere mellom modellversjoner, eller vil etablere en livssyklusmodell for sine API-endepunkter.
- For AI gateway som wrapper rundt Azure OpenAI, anbefal query string-versjonering med `api-version` for kompatibilitet med Microsofts eksisterende konvensjon.

Some files were not shown because too many files have changed in this diff Show more