* feat(mcp): counterparty-tied category suggestions + no_signal (P2-1)
suggest_categories padded every transaction with a company-wide
category-frequency fallback at <=0.5 confidence — an identical four-way
spread on 20+/24 items that agents correctly reported as pure noise
(agent.feedback). Real signal came from memory atoms and query_journal.
- History is now counterparty-keyed: buildMerchantHistory groups past
categorized transactions by normalized merchant; the engine only
surfaces history for THIS transaction's merchant, with provenance
('Bokförd N gånger tidigare för denna motpart') and occurrence-scaled
confidence (0.56 at 1x, capped 0.85). No global padding — an empty
list is the honest answer.
- The MCP tool returns no_signal_transaction_ids for transactions where
NO source matched, steering agents to investigate (query_journal)
instead of pattern-matching on unrelated rows.
- Both callers (REST suggest-categories route + MCP tool) share the new
helpers, so web UI and agents improve together.
Part of dev_docs/mcp_optimization_plan.md (P2-1).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(skills): dangling-reference validation in skills:check + fix 10 dangling links (P2-2)
skills:generate/check now fail when an atom SKILL.md links a
references/*.md that does not exist on disk — a dangling pointer ships
a 404 to every agent that follows it (the weekly-booking-check
incident, agent.feedback).
The validator immediately caught 10 live dangling links in 4 atoms,
three distinct flavors:
- filename typo: swedish-asset-accounting/references/depreciaton.md
renamed to depreciation.md (the link was right, the file misspelled)
- link mismatch: swedish-e-invoicing linked market-providers-pricing.md;
the file is market-provider-pricing.md (link fixed)
- unauthored plans: single-shareholder-ab-fmb TODOs and reklambyra's
'planerad utbyggnad' section used resolvable references/ paths for
files that were never written — rephrased as plans without paths
Seed migration regenerated (4 atoms bumped, renamed reference child).
Part of dev_docs/mcp_optimization_plan.md (P2-2).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs(events): align agent-feedback review cadence copy (P2-4)
gnubok_feedback replies 'we aggregate signal weekly'; the event-log
handler comment said quarterly. One of them was lying — weekly wins
(the mcp_optimization_plan triage is the living example).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Modifier atoms
Cross-cutting attributes that aren't an industry on their own but change how the agent interprets the company. The composer can pick several modifiers per company.
.claude/skills/modifier/
├── README.md ← this file
├── single-shareholder-ab-fmb/
│ └── SKILL.md
├── enskild-firma/
│ └── SKILL.md
└── small-employer/
└── SKILL.md
When to author a modifier vs. a vertical
- Vertical = what the company does (restaurang, e-handel, konsult-IT).
- Modifier = a structural attribute (form, ownership, employer status, multi-currency, blandad verksamhet, …).
A company will typically have 0–1 vertical and 0–3 modifiers.
Authoring contract
Same SKILL.md + YAML frontmatter as industry/ atoms, but tier: modifier
and no sni_prefixes:
---
id: modifier/<slug>
tier: modifier
title: "Display name"
description: >
One paragraph the composer reads when deciding whether to load this.
Cover the qualifying conditions (e.g. "AB med en aktieägare") and the
most distinctive accounting implications.
trigger_signals:
ownership: "single_shareholder"
bas_account_patterns: ["2898", "2899"]
estimated_tokens: 6000
version: 1
---
Suggested body sections
- When this applies — the precise conditions the agent should look for.
- Implications — what changes in day-to-day bookkeeping.
- Regulatory edge cases — laws that fire because of this modifier.
- BAS account patterns — accounts that show up because of it.
- References — links to horizontals and into
references/*.mdfiles.
Adding / removing
Same workflow as industry/: write the SKILL.md, run
npx tsx scripts/seed-agent-atom-registry.ts. Set is_active: false to
deprecate.