feat(ms-ai-architect): C2.2 valgfritt fritekst-felt free-context.md i onboarding (TDD) [skip-docs]

Spor C / C2.2 (#3, akseptanse K3): fanger et fritt prosa-felt i onboarding og
overflater det (kappet) ambient i hver sesjon.

- lib/user-data.mjs: FREE_CONTEXT_FILE (utenfor ORG_FILES — valgfri, teller ikke
  mot fullføring), collapseProse() surfacer fri kontekst som ÉTT felt uansett
  markdown-struktur (ingen stille drop), capValue() ekstrahert (DRY).
- session-start-context.mjs: leser free-context.md valgfritt (ingen count++).
- onboarding-agent.md: ny Phase 6 (valgfri); onboard.md: prosess/Task/status.
- 11 agenter: uniform 6. bullet (grep 11/11).
- Tester FØR kode: user-data 25/25 (+9), test-hooks 11/11 (+1 K3-ambient).

Gates: validate 239/0/0 · kb-update 200 · kb-eval 100 · kb-integrity 192/192
(220 baseline-warns) · discovery 13/13 · gitleaks 3 pre-eksisterende.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-06-22 14:16:00 +02:00
commit 8ff73b7fe3
18 changed files with 225 additions and 11 deletions

View file

@ -34,6 +34,7 @@ Et kompakt sammendrag av virksomhetskonteksten injiseres ambient i hovedøkten v
- `~/.claude/ms-ai-architect/org/security-compliance.md` — Dataklassifisering, policyer, godkjenning - `~/.claude/ms-ai-architect/org/security-compliance.md` — Dataklassifisering, policyer, godkjenning
- `~/.claude/ms-ai-architect/org/architecture-decisions.md` — ADR-er, retningslinjer, preferanser, budsjett - `~/.claude/ms-ai-architect/org/architecture-decisions.md` — ADR-er, retningslinjer, preferanser, budsjett
- `~/.claude/ms-ai-architect/org/business-references.md` — Maler, styringsmodell, nøkkelpersonell - `~/.claude/ms-ai-architect/org/business-references.md` — Maler, styringsmodell, nøkkelpersonell
- `~/.claude/ms-ai-architect/org/free-context.md` — Fri kontekst (valgfri): alt annet virksomheten vil pluginen skal vite
## Process ## Process

View file

@ -43,6 +43,7 @@ Et kompakt sammendrag av virksomhetskonteksten injiseres ambient i hovedøkten v
- `~/.claude/ms-ai-architect/org/security-compliance.md` — Dataklassifisering, policyer, godkjenning - `~/.claude/ms-ai-architect/org/security-compliance.md` — Dataklassifisering, policyer, godkjenning
- `~/.claude/ms-ai-architect/org/architecture-decisions.md` — ADR-er, retningslinjer, preferanser, budsjett - `~/.claude/ms-ai-architect/org/architecture-decisions.md` — ADR-er, retningslinjer, preferanser, budsjett
- `~/.claude/ms-ai-architect/org/business-references.md` — Maler, styringsmodell, nøkkelpersonell - `~/.claude/ms-ai-architect/org/business-references.md` — Maler, styringsmodell, nøkkelpersonell
- `~/.claude/ms-ai-architect/org/free-context.md` — Fri kontekst (valgfri): alt annet virksomheten vil pluginen skal vite
## Assessment Workflow (6 faser) ## Assessment Workflow (6 faser)

View file

@ -180,6 +180,7 @@ Et kompakt sammendrag av virksomhetskonteksten injiseres ambient i hovedøkten v
- `~/.claude/ms-ai-architect/org/security-compliance.md` — Dataklassifisering, policyer, godkjenning - `~/.claude/ms-ai-architect/org/security-compliance.md` — Dataklassifisering, policyer, godkjenning
- `~/.claude/ms-ai-architect/org/architecture-decisions.md` — ADR-er, retningslinjer, preferanser, budsjett - `~/.claude/ms-ai-architect/org/architecture-decisions.md` — ADR-er, retningslinjer, preferanser, budsjett
- `~/.claude/ms-ai-architect/org/business-references.md` — Maler, styringsmodell, nøkkelpersonell - `~/.claude/ms-ai-architect/org/business-references.md` — Maler, styringsmodell, nøkkelpersonell
- `~/.claude/ms-ai-architect/org/free-context.md` — Fri kontekst (valgfri): alt annet virksomheten vil pluginen skal vite
### 3. Validate Against Latest Guidance ### 3. Validate Against Latest Guidance
Use `microsoft_docs_search` to verify: Use `microsoft_docs_search` to verify:

View file

@ -72,6 +72,7 @@ Et kompakt sammendrag av virksomhetskonteksten injiseres ambient i hovedøkten v
- `~/.claude/ms-ai-architect/org/security-compliance.md` — Dataklassifisering, policyer, godkjenning - `~/.claude/ms-ai-architect/org/security-compliance.md` — Dataklassifisering, policyer, godkjenning
- `~/.claude/ms-ai-architect/org/architecture-decisions.md` — ADR-er, retningslinjer, preferanser, budsjett - `~/.claude/ms-ai-architect/org/architecture-decisions.md` — ADR-er, retningslinjer, preferanser, budsjett
- `~/.claude/ms-ai-architect/org/business-references.md` — Maler, styringsmodell, nøkkelpersonell - `~/.claude/ms-ai-architect/org/business-references.md` — Maler, styringsmodell, nøkkelpersonell
- `~/.claude/ms-ai-architect/org/free-context.md` — Fri kontekst (valgfri): alt annet virksomheten vil pluginen skal vite
### 4. Verify Current Pricing ### 4. Verify Current Pricing

View file

@ -29,6 +29,7 @@ Et kompakt sammendrag av virksomhetskonteksten injiseres ambient i hovedøkten v
- `~/.claude/ms-ai-architect/org/security-compliance.md` — Dataklassifisering, policyer, godkjenning - `~/.claude/ms-ai-architect/org/security-compliance.md` — Dataklassifisering, policyer, godkjenning
- `~/.claude/ms-ai-architect/org/architecture-decisions.md` — ADR-er, retningslinjer, preferanser, budsjett - `~/.claude/ms-ai-architect/org/architecture-decisions.md` — ADR-er, retningslinjer, preferanser, budsjett
- `~/.claude/ms-ai-architect/org/business-references.md` — Maler, styringsmodell, nøkkelpersonell - `~/.claude/ms-ai-architect/org/business-references.md` — Maler, styringsmodell, nøkkelpersonell
- `~/.claude/ms-ai-architect/org/free-context.md` — Fri kontekst (valgfri): alt annet virksomheten vil pluginen skal vite
## Diagramtyper ## Diagramtyper

View file

@ -35,6 +35,7 @@ Et kompakt sammendrag av virksomhetskonteksten injiseres ambient i hovedøkten v
- `~/.claude/ms-ai-architect/org/security-compliance.md` — Dataklassifisering, policyer, godkjenning - `~/.claude/ms-ai-architect/org/security-compliance.md` — Dataklassifisering, policyer, godkjenning
- `~/.claude/ms-ai-architect/org/architecture-decisions.md` — ADR-er, retningslinjer, preferanser, budsjett - `~/.claude/ms-ai-architect/org/architecture-decisions.md` — ADR-er, retningslinjer, preferanser, budsjett
- `~/.claude/ms-ai-architect/org/business-references.md` — Maler, styringsmodell, nøkkelpersonell - `~/.claude/ms-ai-architect/org/business-references.md` — Maler, styringsmodell, nøkkelpersonell
- `~/.claude/ms-ai-architect/org/free-context.md` — Fri kontekst (valgfri): alt annet virksomheten vil pluginen skal vite
## AI Act-integrasjon ## AI Act-integrasjon

View file

@ -26,6 +26,7 @@ Et kompakt sammendrag av virksomhetskonteksten injiseres ambient i hovedøkten v
- `~/.claude/ms-ai-architect/org/security-compliance.md` — Dataklassifisering, policyer, godkjenning - `~/.claude/ms-ai-architect/org/security-compliance.md` — Dataklassifisering, policyer, godkjenning
- `~/.claude/ms-ai-architect/org/architecture-decisions.md` — ADR-er, retningslinjer, preferanser, budsjett - `~/.claude/ms-ai-architect/org/architecture-decisions.md` — ADR-er, retningslinjer, preferanser, budsjett
- `~/.claude/ms-ai-architect/org/business-references.md` — Maler, styringsmodell, nøkkelpersonell - `~/.claude/ms-ai-architect/org/business-references.md` — Maler, styringsmodell, nøkkelpersonell
- `~/.claude/ms-ai-architect/org/free-context.md` — Fri kontekst (valgfri): alt annet virksomheten vil pluginen skal vite
## Your Mission ## Your Mission

View file

@ -12,7 +12,7 @@ tools: ["Read", "Write", "Glob", "AskUserQuestion"]
# Onboarding Agent — Virksomhetstilpasning # Onboarding Agent — Virksomhetstilpasning
You are an onboarding specialist for the AI Architect plugin. You conduct a structured interview across 5 categories to collect organization-specific context. This context is stored in the user-owned org directory and used by all other agents for tailored recommendations. You are an onboarding specialist for the AI Architect plugin. You conduct a structured interview across 5 categories — plus an optional free-text note (Phase 6) — to collect organization-specific context. This context is stored in the user-owned org directory and used by all other agents for tailored recommendations.
## Language Instruction ## Language Instruction
@ -26,10 +26,10 @@ Orkestratoren (`/architect:onboard`) gir deg en **absolutt** datakatalog (`~/.cl
On start, check for existing onboarding state: On start, check for existing onboarding state:
1. Use Glob on the provided data directory to see which of the 5 files are present 1. Use Glob on the provided data directory to see which of the 5 structured files are present
2. For each existing file, read it to check for `completed: true` in frontmatter 2. For each existing file, read it to check for `completed: true` in frontmatter
3. Skip completed categories, resume from first incomplete category 3. Skip completed categories, resume from first incomplete category
4. If all 5 files exist with `completed: true`, show completion report and exit 4. If all 5 structured files exist with `completed: true`: run the optional Phase 6 only if `free-context.md` is absent (don't re-prompt it when it already exists), then show the completion report and exit
## Interview Phases ## Interview Phases
@ -110,9 +110,34 @@ Collect:
After answers, write `business-references.md` to the data directory. After answers, write `business-references.md` to the data directory.
### Phase 6: Fri kontekst (`org/free-context.md`) — VALGFRI
Et enkelt fritekst-felt for alt de strukturerte spørsmålene ikke fanget. Still ÉTT åpent spørsmål (vanlig prompt, ikke AskUserQuestion):
> «Er det noe annet du vil at AI Architect skal vite om virksomheten din? F.eks. pågående initiativer, smertepunkter, tidligere AI-/sky-hendelser, strategiske føringer, eller preferanser — alt som gjør rådene mer treffsikre. (Valgfritt — trykk enter / skriv «hopp over» for å hoppe over.)»
- **Hvis brukeren gir tekst:** skriv `free-context.md` til datakatalogen med brukerens prosa gjengitt ordrett (ikke omskriv eller forkort):
```markdown
---
category: free-context
completed: true
last_updated: [YYYY-MM-DD]
---
# Fri kontekst
## Fri kontekst
[brukerens fritekst, ordrett]
```
- **Hvis brukeren hopper over / svarer tomt:** IKKE skriv fila. Fri kontekst er valgfri og teller ikke mot fullføring (de 5 strukturerte filene er fullføringskontrakten).
Sammendraget som injiseres ambient ved sesjonsstart kapper fri-konteksten til et lengde-budsjett; den fulle teksten leses av agenter direkte fra fila. Hold derfor det viktigste først i prosaen.
## Completion Report ## Completion Report
After all 5 phases, present: After the 5 structured phases (and the optional Phase 6), present:
``` ```
## Onboarding komplett ## Onboarding komplett
@ -124,6 +149,7 @@ After all 5 phases, present:
| Sikkerhet og compliance | Fullført | [dato] | | Sikkerhet og compliance | Fullført | [dato] |
| Arkitekturbeslutninger | Fullført | [dato] | | Arkitekturbeslutninger | Fullført | [dato] |
| Forretningsreferanser | Fullført | [dato] | | Forretningsreferanser | Fullført | [dato] |
| Fri kontekst (valgfri) | [Lagt til / Hoppet over] | [dato] |
### Neste steg ### Neste steg
@ -142,7 +168,7 @@ Pluginen er nå tilpasset din virksomhet. Prøv:
- Accept "vet ikke" / "usikker" as valid answers — note as "Ikke avklart" - Accept "vet ikke" / "usikker" as valid answers — note as "Ikke avklart"
- If user wants to skip a category, write the file with `completed: false` and note which questions were skipped - If user wants to skip a category, write the file with `completed: false` and note which questions were skipped
- Keep each phase focused — 2-3 questions, then write file and move on - Keep each phase focused — 2-3 questions, then write file and move on
- All 5 files are written DIRECTLY into the provided user-owned data directory (absolute path), never the plugin root - All files (the 5 structured ones + the optional `free-context.md`) are written DIRECTLY into the provided user-owned data directory (absolute path), never the plugin root
## Error Handling ## Error Handling

View file

@ -29,6 +29,7 @@ Et kompakt sammendrag av virksomhetskonteksten injiseres ambient i hovedøkten v
- `~/.claude/ms-ai-architect/org/security-compliance.md` — Dataklassifisering, policyer, godkjenning - `~/.claude/ms-ai-architect/org/security-compliance.md` — Dataklassifisering, policyer, godkjenning
- `~/.claude/ms-ai-architect/org/architecture-decisions.md` — ADR-er, retningslinjer, preferanser, budsjett - `~/.claude/ms-ai-architect/org/architecture-decisions.md` — ADR-er, retningslinjer, preferanser, budsjett
- `~/.claude/ms-ai-architect/org/business-references.md` — Maler, styringsmodell, nøkkelpersonell - `~/.claude/ms-ai-architect/org/business-references.md` — Maler, styringsmodell, nøkkelpersonell
- `~/.claude/ms-ai-architect/org/free-context.md` — Fri kontekst (valgfri): alt annet virksomheten vil pluginen skal vite
## Lokal KB-baseline (betinget — RAG / MLOps / engineering-temaer) ## Lokal KB-baseline (betinget — RAG / MLOps / engineering-temaer)

View file

@ -53,6 +53,7 @@ Et kompakt sammendrag av virksomhetskonteksten injiseres ambient i hovedøkten v
- `~/.claude/ms-ai-architect/org/security-compliance.md` — Dataklassifisering, policyer, godkjenning - `~/.claude/ms-ai-architect/org/security-compliance.md` — Dataklassifisering, policyer, godkjenning
- `~/.claude/ms-ai-architect/org/architecture-decisions.md` — ADR-er, retningslinjer, preferanser, budsjett - `~/.claude/ms-ai-architect/org/architecture-decisions.md` — ADR-er, retningslinjer, preferanser, budsjett
- `~/.claude/ms-ai-architect/org/business-references.md` — Maler, styringsmodell, nøkkelpersonell - `~/.claude/ms-ai-architect/org/business-references.md` — Maler, styringsmodell, nøkkelpersonell
- `~/.claude/ms-ai-architect/org/free-context.md` — Fri kontekst (valgfri): alt annet virksomheten vil pluginen skal vite
## 4 ekspertperspektiver ## 4 ekspertperspektiver

View file

@ -38,6 +38,7 @@ Et kompakt sammendrag av virksomhetskonteksten injiseres ambient i hovedøkten v
- `~/.claude/ms-ai-architect/org/security-compliance.md` — Dataklassifisering, policyer, godkjenning - `~/.claude/ms-ai-architect/org/security-compliance.md` — Dataklassifisering, policyer, godkjenning
- `~/.claude/ms-ai-architect/org/architecture-decisions.md` — ADR-er, retningslinjer, preferanser, budsjett - `~/.claude/ms-ai-architect/org/architecture-decisions.md` — ADR-er, retningslinjer, preferanser, budsjett
- `~/.claude/ms-ai-architect/org/business-references.md` — Maler, styringsmodell, nøkkelpersonell - `~/.claude/ms-ai-architect/org/business-references.md` — Maler, styringsmodell, nøkkelpersonell
- `~/.claude/ms-ai-architect/org/free-context.md` — Fri kontekst (valgfri): alt annet virksomheten vil pluginen skal vite
## Your Mission ## Your Mission

View file

@ -44,6 +44,7 @@ Et kompakt sammendrag av virksomhetskonteksten injiseres ambient i hovedøkten v
- `~/.claude/ms-ai-architect/org/security-compliance.md` — Dataklassifisering, policyer, godkjenning - `~/.claude/ms-ai-architect/org/security-compliance.md` — Dataklassifisering, policyer, godkjenning
- `~/.claude/ms-ai-architect/org/architecture-decisions.md` — ADR-er, retningslinjer, preferanser, budsjett - `~/.claude/ms-ai-architect/org/architecture-decisions.md` — ADR-er, retningslinjer, preferanser, budsjett
- `~/.claude/ms-ai-architect/org/business-references.md` — Maler, styringsmodell, nøkkelpersonell - `~/.claude/ms-ai-architect/org/business-references.md` — Maler, styringsmodell, nøkkelpersonell
- `~/.claude/ms-ai-architect/org/free-context.md` — Fri kontekst (valgfri): alt annet virksomheten vil pluginen skal vite
## Output Format: Technical Summary ## Output Format: Technical Summary

View file

@ -44,8 +44,9 @@ Hvis argumentet inneholder `--status`:
| Sikkerhet og compliance | security-compliance.md | [Fullført/Mangler] | [dato] | | Sikkerhet og compliance | security-compliance.md | [Fullført/Mangler] | [dato] |
| Arkitekturbeslutninger | architecture-decisions.md | [Fullført/Mangler] | [dato] | | Arkitekturbeslutninger | architecture-decisions.md | [Fullført/Mangler] | [dato] |
| Forretningsreferanser | business-references.md | [Fullført/Mangler] | [dato] | | Forretningsreferanser | business-references.md | [Fullført/Mangler] | [dato] |
| Fri kontekst (valgfri) | free-context.md | [Lagt til/Ikke satt] | [dato] |
**Fullført:** X/5 kategorier (XX%) — lagret i `$ORG_DIR` **Fullført:** X/5 kategorier (XX%) — lagret i `$ORG_DIR`. Fri kontekst er valgfri og teller ikke mot prosenten.
``` ```
4. Hvis noen mangler, tilby å kjøre `/architect:onboard` for å fullføre 4. Hvis noen mangler, tilby å kjøre `/architect:onboard` for å fullføre
@ -66,6 +67,7 @@ Prosessen tar ca. 5 minutter og dekker:
3. Sikkerhet og compliance (dataklassifisering, residens) 3. Sikkerhet og compliance (dataklassifisering, residens)
4. Arkitekturbeslutninger (plattform, integrasjoner, budsjett) 4. Arkitekturbeslutninger (plattform, integrasjoner, budsjett)
5. Forretningsreferanser (styringsmodell, dokumentformat) 5. Forretningsreferanser (styringsmodell, dokumentformat)
6. Fri kontekst (valgfritt — alt annet du vil pluginen skal vite)
``` ```
Deretter start onboarding-agenten (se under). Deretter start onboarding-agenten (se under).
@ -82,8 +84,9 @@ Gjennomfør onboarding-intervju for å samle virksomhetsspesifikk kontekst.
Datakatalog (absolutt, bruker-eid): <$ORG_DIR fra Datakatalog-steget> Datakatalog (absolutt, bruker-eid): <$ORG_DIR fra Datakatalog-steget>
Eksisterende org-filer: [list files that exist, or 'ingen'] Eksisterende org-filer: [list files that exist, or 'ingen']
Skriv resultater til denne absolutte katalogen (IKKE plugin-roten). Kjør alle 5 faser i Skriv resultater til denne absolutte katalogen (IKKE plugin-roten). Kjør alle 5 strukturerte faser i
rekkefølge, hopp over kategorier som allerede har completed: true." rekkefølge, hopp over kategorier som allerede har completed: true, og avslutt med den valgfrie
Phase 6 (fri kontekst → free-context.md) hvis den ikke allerede finnes."
``` ```
## Etter fullført onboarding ## Etter fullført onboarding

View file

@ -132,3 +132,17 @@ C2.1 er den bærende delsesjonen (etablerer lagring + resolver alle andre bygger
- **Risiko 1 BEVIST:** Task-spawnet subagent arver **IKKE** SessionStart-injeksjonen (live-probe) → agentene bæres av fallback-fil-lesing; `Read`/`Glob` ekspanderer `~` (verifisert) → bruker-sti lesbar uten Bash. - **Risiko 1 BEVIST:** Task-spawnet subagent arver **IKKE** SessionStart-injeksjonen (live-probe) → agentene bæres av fallback-fil-lesing; `Read`/`Glob` ekspanderer `~` (verifisert) → bruker-sti lesbar uten Bash.
- **Verifisert:** user-data 16/16 · detection-schedule 23/23 (+2 round-trip) · test-hooks 10/10 (+4: K1-injeksjon + tom-org-negativ) · kb-update 191 · kb-eval 100 · validate PASSED (0/0) · kb-integrity 192/192 (220 baseline-warns) · discovery 13/13 · gitleaks 3 PRE-EKSISTERENDE (`playground/vendor/`). CLAUDE.md trengte ingen sti-endring (kun kommando/agent-omtale); `.gitignore org/` beholdt som forsvar-i-dybden. - **Verifisert:** user-data 16/16 · detection-schedule 23/23 (+2 round-trip) · test-hooks 10/10 (+4: K1-injeksjon + tom-org-negativ) · kb-update 191 · kb-eval 100 · validate PASSED (0/0) · kb-integrity 192/192 (220 baseline-warns) · discovery 13/13 · gitleaks 3 PRE-EKSISTERENDE (`playground/vendor/`). CLAUDE.md trengte ingen sti-endring (kun kommando/agent-omtale); `.gitignore org/` beholdt som forsvar-i-dybden.
- **Neste:** C2.2 (fritekst-felt `org/free-context.md` → fanges av onboarding + inkluderes kappet i `buildOrgSummary`). - **Neste:** C2.2 (fritekst-felt `org/free-context.md` → fanges av onboarding + inkluderes kappet i `buildOrgSummary`).
### C2.2 — RESULTAT (levert, TDD test FØR kode)
**Mål nådd:** valgfritt fri-prosa-felt `free-context.md` fanges i onboarding og overflater (kappet) i det ambiente sammendraget → **K3 oppfylt**.
- **Designvalg som avvek fra startnotatet (begrunnet):** `free-context.md` ble **IKKE** lagt i `ORG_FILES`. `ORG_FILES` er doblet brukt i hooken — både fil-lesing OG fullføringskontrakt (`orgComplete < ORG_FILES.length`). Hadde fila blitt en sjette `ORG_FILES`-oppføring, ville en fullt onboardet bruker uten fritekst vist «Onboarding 5/6 — kjør for å fullføre». Løst med egen `export const FREE_CONTEXT_FILE` (utenfor `ORG_FILES`); hooken leser den **uten å telle** den.
- **`lib/user-data.mjs`:** `FREE_CONTEXT_FILE` + `FREE_CONTEXT_LABEL='Fri kontekst'`. `collapseProse()` (strip frontmatter + ALLE header-linjer + kollaps whitespace) → fri kontekst overflates som ÉTT felt **uansett markdown-struktur** (rå prosa, kun H1, eller H2) — fjerner stille-drop-feilmodus som ellers truet K3. `capValue()` ekstrahert (DRY — brukes nå av både strukturert-loop og fri-kontekst). I `buildOrgSummary` legges fri kontekst SIST, kappet av samme `maxValueLen` (160) som øvrige felt.
- **`session-start-context.mjs`:** leser `FREE_CONTEXT_FILE` valgfritt inn i `files`-mappen (ingen `count++`) → ambient-summary inkluderer den; fullføringstellingen uendret.
- **`onboarding-agent.md`:** ny **Phase 6 (VALGFRI)** — ett åpent fritekst-spørsmål; skriver `free-context.md` ordrett kun hvis bruker gir tekst (hopper over → ingen fil). Resume-logikk + completion-report + retningslinjer oppdatert (5 strukturerte = fullføringskontrakt; fri kontekst valgfri 6.).
- **`commands/onboard.md`:** prosess-liste (6. fri kontekst, valgfritt), Task-prompt (kjør Phase 6 hvis fila mangler), status-tabell (egen valgfri-rad; teller ikke i X/5).
- **11 agenter:** uniform 6. bullet `free-context.md — Fri kontekst (valgfri) …` (grep 11/11).
- **Kapp-tradeoff (bevisst):** fri kontekst kappes til `maxValueLen` (160) i det ambiente teaser-et — K3 krever bare «kappet til budsjett»-synlighet, og agentene leser full fil via fallback. Egen, mer raus fri-kontekst-cap er en triviell oppfølging hvis 160 viser seg for kort i praksis (ikke gjort — unngår knott uten påvist behov).
- **Verifisert:** user-data 25/25 (+9 fri-kontekst) · test-hooks 11/11 (+1: K3-ambient) · kb-update 200 · kb-eval 100 · validate PASSED (239/0/0) · kb-integrity 192/192 (220 baseline-warns) · discovery 13/13 · gitleaks 3 PRE-EKSISTERENDE (`playground/vendor/`).
- **Neste:** C2.3 (`os_scheduler_cadence` + `enabled` skrives av onboarding; round-trip mot `parseScheduleConfig`).

View file

@ -14,6 +14,7 @@ import {
import { import {
resolveOrgDir, resolveOrgDir,
ORG_FILES, ORG_FILES,
FREE_CONTEXT_FILE,
buildOrgSummary, buildOrgSummary,
} from '../../scripts/kb-update/lib/user-data.mjs'; } from '../../scripts/kb-update/lib/user-data.mjs';
@ -130,6 +131,16 @@ function readOrgFiles(dir) {
} }
} }
} }
// Optional free-prose context (C2.2): read it for the ambient summary, but
// do NOT count it — it is optional and must not affect onboarding completeness.
const fp = join(dir, FREE_CONTEXT_FILE);
if (existsSync(fp)) {
try {
files[FREE_CONTEXT_FILE] = readFileSync(fp, 'utf8');
} catch {
// Unreadable — skip; advisory only
}
}
} }
return { files, count }; return { files, count };
} }

View file

@ -32,6 +32,14 @@ export const ORG_FILES = Object.freeze([
'business-references.md', 'business-references.md',
]); ]);
// The optional free-prose file (C2.2, #3): "everything else you want the plugin
// to know". Deliberately NOT in ORG_FILES — its presence is optional and must
// NOT affect the onboarding-completeness count (the SessionStart hook gates that
// on `count < ORG_FILES.length`). It is read for the ambient summary only.
export const FREE_CONTEXT_FILE = 'free-context.md';
const FREE_CONTEXT_LABEL = 'Fri kontekst';
const DEFAULT_SUMMARY_CAP = 25; // max summary lines (hook-injection budget) const DEFAULT_SUMMARY_CAP = 25; // max summary lines (hook-injection budget)
const DEFAULT_MAX_VALUE_LEN = 160; // per-field char cap (free-text guard) const DEFAULT_MAX_VALUE_LEN = 160; // per-field char cap (free-text guard)
@ -89,6 +97,30 @@ function extractSections(content) {
return out; return out;
} }
/**
* Collapse a markdown document to one prose line: drop frontmatter and every
* header line, then squeeze whitespace. Used for the free-context file, which is
* ONE free field (not structured H2 sections) and may be plain prose so it is
* surfaced whole rather than per-section, never silently dropped. Pure.
* @param {string} content
* @returns {string}
*/
function collapseProse(content) {
return stripFrontmatter(content)
.split('\n')
.filter((line) => !/^#{1,6}\s/.test(line))
.join(' ')
.replace(/\s+/g, ' ')
.trim();
}
/** Truncate a field value to maxValueLen, appending an ellipsis when cut. Pure. */
function capValue(value, maxValueLen) {
return value.length > maxValueLen
? `${value.slice(0, maxValueLen - 1).trimEnd()}`
: value;
}
/** /**
* Build a compact, deterministic org-context summary from org file contents. * Build a compact, deterministic org-context summary from org file contents.
* PURE takes a `{ filename: contentString }` map (the caller reads the files) * PURE takes a `{ filename: contentString }` map (the caller reads the files)
@ -113,12 +145,19 @@ export function buildOrgSummary(orgFiles, opts = {}) {
const content = orgFiles[name]; const content = orgFiles[name];
if (typeof content !== 'string' || !content.trim()) continue; if (typeof content !== 'string' || !content.trim()) continue;
for (const [header, value] of extractSections(content)) { for (const [header, value] of extractSections(content)) {
const trimmed = fields.push(`${header}: ${capValue(value, maxValueLen)}`);
value.length > maxValueLen ? `${value.slice(0, maxValueLen - 1).trimEnd()}` : value;
fields.push(`${header}: ${trimmed}`);
} }
} }
// Free-prose context (C2.2, #3): the optional sixth file, surfaced LAST as one
// "Fri kontekst" field regardless of internal markdown structure, so a plain
// paragraph is never silently dropped (acceptance K3). Capped like any field.
const freeContent = orgFiles[FREE_CONTEXT_FILE];
if (typeof freeContent === 'string' && freeContent.trim()) {
const body = collapseProse(freeContent);
if (body) fields.push(`${FREE_CONTEXT_LABEL}: ${capValue(body, maxValueLen)}`);
}
if (fields.length === 0) return ''; if (fields.length === 0) return '';
if (fields.length <= cap) return fields.join('\n'); if (fields.length <= cap) return fields.join('\n');

View file

@ -19,6 +19,7 @@ import {
USER_DATA_DIRNAME, USER_DATA_DIRNAME,
CONFIG_FILENAME, CONFIG_FILENAME,
ORG_FILES, ORG_FILES,
FREE_CONTEXT_FILE,
resolveUserDataDir, resolveUserDataDir,
resolveOrgDir, resolveOrgDir,
resolveConfigPath, resolveConfigPath,
@ -173,3 +174,92 @@ test('buildOrgSummary — default cap keeps the summary compact (<= 25 lines)',
const lines = s.split('\n').filter(Boolean); const lines = s.split('\n').filter(Boolean);
assert.ok(lines.length <= 25, `default cap should keep <=25 lines, got ${lines.length}`); assert.ok(lines.length <= 25, `default cap should keep <=25 lines, got ${lines.length}`);
}); });
// ===========================================================================
// (C) Free-prose context (C2.2) — the optional sixth file (#3, acceptance K3)
// ===========================================================================
test('FREE_CONTEXT_FILE — optional free-prose filename, NOT part of ORG_FILES', () => {
assert.equal(FREE_CONTEXT_FILE, 'free-context.md');
assert.ok(
!ORG_FILES.includes(FREE_CONTEXT_FILE),
'free-context is optional and must not count toward onboarding completeness',
);
});
const FREE = [
'---',
'category: free-context',
'completed: true',
'last_updated: 2026-06-22',
'---',
'',
'# Fri kontekst',
'',
'## Fri kontekst',
'Vi migrerer fra on-prem til Azure i 2026.',
'',
].join('\n');
test('buildOrgSummary — surfaces free-context as a "Fri kontekst" field', () => {
const s = buildOrgSummary({ 'free-context.md': FREE });
assert.match(s, /Fri kontekst: Vi migrerer fra on-prem til Azure i 2026\./);
});
test('buildOrgSummary — free-context is robust to raw prose without any H2 (K3: no silent drop)', () => {
// The whole point of #3 is a single free field; it must surface even when the
// agent writes a plain paragraph with no markdown structure at all.
const s = buildOrgSummary({
'free-context.md': 'Vi har hatt en hendelse med Copilot som lekket interne dokumenter.',
});
assert.match(s, /Fri kontekst: Vi har hatt en hendelse med Copilot/);
});
test('buildOrgSummary — free-context strips frontmatter and all header lines', () => {
const s = buildOrgSummary({
'free-context.md': '---\ncategory: free-context\n---\n# Fri kontekst\n## Fri kontekst\nKun prosaen skal vises.\n',
});
assert.doesNotMatch(s, /category:/, 'frontmatter stripped');
assert.equal(s, 'Fri kontekst: Kun prosaen skal vises.');
});
test('buildOrgSummary — free-context appears AFTER the structured fields', () => {
const out = buildOrgSummary({
'free-context.md': '## Fri kontekst\nTilleggsnotat.',
'organization-profile.md': PROFILE,
});
assert.ok(
out.indexOf('Sektortype') < out.indexOf('Fri kontekst'),
'structured context leads; free prose trails',
);
});
test('buildOrgSummary — long free-context is capped with an ellipsis (budget guard)', () => {
const s = buildOrgSummary({ 'free-context.md': 'y'.repeat(500) }, { maxValueLen: 80 });
const line = s.split('\n').find((l) => l.startsWith('Fri kontekst:'));
assert.ok(line, 'free-context line present');
assert.match(line, /…$/, 'truncation marker appended');
assert.ok(line.length <= 'Fri kontekst: '.length + 80, `line too long: ${line.length}`);
});
test('buildOrgSummary — empty/whitespace/header-only free-context yields no field', () => {
assert.equal(buildOrgSummary({ 'free-context.md': ' \n\n' }), '');
assert.equal(
buildOrgSummary({ 'free-context.md': '---\ncategory: free-context\n---\n# Fri kontekst\n' }),
'',
'frontmatter + bare H1 (no prose) => nothing',
);
});
test('buildOrgSummary — free-context absent leaves the structured summary unchanged (back-compat)', () => {
const s = buildOrgSummary({ 'organization-profile.md': PROFILE });
assert.doesNotMatch(s, /Fri kontekst/);
});
test('buildOrgSummary — realistic full onboarding keeps free-context visible (K3)', () => {
const all = {};
for (const f of ORG_FILES) all[f] = `## ${f}-felt\nverdi for ${f}`;
all['free-context.md'] = '## Fri kontekst\nViktig tilleggskontekst som må være synlig.';
const s = buildOrgSummary(all); // default cap 25
assert.match(s, /Fri kontekst: Viktig tilleggskontekst/, 'free-context visible within default budget');
});

View file

@ -58,6 +58,20 @@ Statlig
Testetaten Testetaten
ORGEOF ORGEOF
# C2.2: optional free-prose file — read for the ambient summary, NOT counted
# toward onboarding completeness. Proves K3 (free-text visible in interaction).
cat > "$TMPHOME/.claude/ms-ai-architect/org/free-context.md" <<'FREEEOF'
---
category: free-context
completed: true
---
# Fri kontekst
## Fri kontekst
Vi migrerer fra on-prem til Azure i 2026.
FREEEOF
OUTPUT=$(CLAUDE_PLUGIN_ROOT="$PLUGIN_ROOT" HOME="$TMPHOME" node "$SCRIPTS_DIR/session-start-context.mjs" 2>/dev/null) OUTPUT=$(CLAUDE_PLUGIN_ROOT="$PLUGIN_ROOT" HOME="$TMPHOME" node "$SCRIPTS_DIR/session-start-context.mjs" 2>/dev/null)
if echo "$OUTPUT" | grep -q "Virksomhetskontekst (auto-injisert"; then if echo "$OUTPUT" | grep -q "Virksomhetskontekst (auto-injisert"; then
@ -72,6 +86,12 @@ else
fail "Ambient block missing org fact" fail "Ambient block missing org fact"
fi fi
if echo "$OUTPUT" | grep -q "Fri kontekst: Vi migrerer fra on-prem til Azure"; then
pass "Ambient block surfaces optional free-context (K3)"
else
fail "Ambient block missing free-context content (K3)"
fi
# Empty home (no user org, no plugin org) => onboarding nudge, NO ambient block. # Empty home (no user org, no plugin org) => onboarding nudge, NO ambient block.
TMPHOME2=$(mktemp -d) TMPHOME2=$(mktemp -d)
OUTPUT=$(CLAUDE_PLUGIN_ROOT="$PLUGIN_ROOT" HOME="$TMPHOME2" node "$SCRIPTS_DIR/session-start-context.mjs" 2>/dev/null) OUTPUT=$(CLAUDE_PLUGIN_ROOT="$PLUGIN_ROOT" HOME="$TMPHOME2" node "$SCRIPTS_DIR/session-start-context.mjs" 2>/dev/null)