petasos-finance-vaultSAFE
General household-finance skill for Hermes Agent — Obsidian vault, append-only JSONL ledger, pluggable bank-email adapters, verification gates, month close.
Overview
From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.
A Hermes Agent skill for running a household-finance vault in Obsidian on a ledger architecture:
- Append-only JSONL ledger as the single source of truth — every manual
edit goes through a validated CLI (python3 -m petasos.ledger add|relabel); hand-editing the JSONL is disallowed
- All intelligence is DATA you own:
banks.yaml(bank email formats) and
rules.md (classification: auto-post / aggregate / needs-confirm / plumbing tiers, plus the §5 kind-routing table) live in your vault and shadow the bundled examples — the engine is generic and never user-edited
- Bank alert emails as the primary evidence source (AgentMail inbox,
or any REST-compatible endpoint)
- Arithmetic verification gates (ID uniqueness, balances arithmetic,
transaction chain, frozen months) that must pass after EVERY write — --dry previews everything and writes nothing
- Frozen month closes: preconditions enforced (gates green, zero
needs-confirm), expense totals frozen immutably, full-ledger snapshot archived as a restore point
- Concurrent-run safety: live runs serialize on a lockfile; an
overlapping run exits loudly instead of double-writing
Python 3.10+ stdlib + PyYAML (pip install pyyaml) — the only dependency, and its absence fails loud by design.
How it works
flowchart LR
A["Bank alert emails"] -->|"REST fetch, dedupe by seen/subject/old_ref"| B["pipeline.py daily sync"]
B -->|"banks.yaml adapters parse"| C{"Chain-verify:bal(n) = bal(n-1) -/+ amount(batched ± pair = one alert)"}
C -->|"mismatch → append NOTHING,exit 1"| X["Parse bug orunalerted txn"]
C -->|"ok"| D["Classify via rules.md§6 confirmed → never re-asked,§3a merchants, §1 patterns,§5 kind-routing tiers"]
D -->|"auto tiers"| E["Append JSONL ledger(lockfile held; re-read verified)"]
D -->|"unknown ≥ threshold/ mystery credit"| I["Digest asks the user ONCE"]
I -->|79e771c005e6OBSERVED · 2026-10-14Install
Commands as the repository documents them. They are shown, not run.
pip install pyyaml
pip install pyyaml
What it tells the agent
The instruction file, verbatim from the audited commit — this is the text the model reads, and the surface the audit's instruction layer examines. Quoted here so you can judge it without cloning anything.
---
name: petasos-finance-vault
description: Run an Obsidian household-finance ledger vault with gates.
version: 1.0.0
author: Nhut Duong (nhutdm), Hermes Agent
license: MIT
platforms: [linux, macos]
metadata:
hermes:
tags: [Obsidian, Finance, Ledger, Household]
related_skills: [obsidian]
config:
- key: petasos.vault_path
description: Absolute path to the Obsidian vault holding the finance area
default: ""
prompt: Obsidian vault path (e.g. ~/Obsidian/MyVault)
blueprint:
schedule: "0 7 * * *"
deliver: origin
prompt: "Petasos daily sync: fetch bank alert emails, parse, chain-verify, classify per rules.md, append ledger rows, update balances, send the needs-confirm digest, regenerate views."
required_environment_variables:
- name: AGENTMAIL_API_KEY
prompt: AgentMail API key
help: Get one at https://agentmail.to
required_for: bank-alert email fetch in the daily pipeline
- name: PETASOS_INBOX
prompt: AgentMail inbox address receiving bank alerts
help: The mailbox your banks send transaction alerts to
required_for: daily pipeline email fetch
---
# Petasos Finance Vault
A household-finance vault for Obsidian built on a ledger architecture: an
append-only JSONL ledger as the single source of truth, a human-editable
classification rules file, generated dashboard views, and arithmetic
verification gates that must pass after every write. Bank alert emails are the
primary transaction evidence source.
The engine is split into a generic Python package (`petasos/`) plus thin
CLI wrappers (`scripts/`), with ALL bank/merchant intelligence in data you
own
(`banks.yaml`, `rules.md`) inside your vault. Manual ledger edits go through
a validated CLI (`python3 -m petasos.ledger`) — hand-editing the JSONL is
disallowed. Live runs are serialized by a lockfile, months freeze at close,
and every write re-runs the full gate set.
## When to Use
- Any task touching the vault named by `petasos.vault_path`: ledger appends,
balance updates, classification rules, view regeneration, month close.
- Syncing transactions from bank notification emails into the ledger.
- Logging chat-reported items (cash spending, app-screenshot transactions,
user corrections) or correcting/confirming existing rows.
- Reconciling, auditing accounts, or answering balance/spend questions from
the ledger.
Don't use for: generic Obsidian mechanics (use the `obsidian` skill);
budgeting philosophy questions that never touch the ledger.
## Requirements & Install
- Python 3.10+ (stdlib) and PyYAML — the ONLY dependency:
`pip install pyyaml`. A missing PyYAML fails LOUD by design with the
install hint and exit code 2 (INV-2); nothing degrades silently.
- Env vars `AGENTMAIL_API_KEY` + `PETASOS_INBOX` for email fetch; vault path
via `hermes config set skills.config.petasos.vault_path <abs path>` or
`export PETASOS_VAULT=<abs path>`.
## Architecture — the engine/data split
The engine is generic and is NEVER user-edited:
- `petasos/` — ledger, chain checks, classifier, gates, views, close,
scaffolder (all bank-agnostic logic).
- `scripts/` — thin CLI wrappers over the package.
All intelligence lives in DATA inside your vault, resolved through a
shadowing chain (first existing file wins):
| Data | Chain (first hit wins) | Loud when |
|---|---|---|
| Bank formats | `$PETASOS_BANKS` → `<ledger_dir>/banks.yaml` → bundled `banks.yaml` | env var names a missing file |
| Classification | `$PETASOS_RULES` → `<ledger_dir>/rules.md` → bundled `templates/rules.md` | env var names a missing file |
An env var that names a nonexistent path is a LOUD error listing every
searched path (exit 2) — never a silent fallback to examples. Run
`python3 scripts/bank_adapters.py --banks` to see which registry is active.
`rules.md` is the classification brain: auto-post patterns (§1), aggregate
rules (§2), known-merchant routing (§3a), needs-confirm rules (§3), plumbing
(§4), the §5 kind-routing table mapping each parsed bank-alert kind to a tier
default (`expense` / `expense-under-thresh` / `balance-alert` / `plumbing` /
`transfer-receipt`), and §6 confirmed-by-user items that are never re-asked.
No bank or merchant name is ever hardcoded in Python.
Privacy pillar: this repo is a public generic engine. Real account numbers,
names, IPs, card fragments, or any private deployment detail never belong in
it — bank entries in the bundled `banks.yaml` are worked examples only.
## Vault Structure
```
<Vault>/2-Areas/Finance/_Ledger/
transactions.jsonl # append-only; one JSON object per line (edits: DG-16 CLI only)
balances.json # accounts + DERIVED snapshot_totals (totals recomputed by gen_views)
closed_months.json # frozen month EXPENSE totals — IMMUTABLE once written
state.json # pipeline seen-threads (written by the pipeline only)
rules.md # classification brain — human-editable data
banks.yaml # bank adapter registry — human-editable data
fixtures/ # captured emails + expected.yaml — adapter regression corpus
gen_views.py # if present, the vault's own copy shadows the bundled one
petasos.lock # run lock — exists only while a live pipeline run writes
2-Areas/Finance/ # generated views (Dashboards.md, Salary History.md) + reference notes
4-Archives/Finance/YYYY-MM/ # closed-month archive: full-ledger snapshot + Monthly Review
```
Views (`Dashboards.md`, `Salary History.md`) are GENERATED — never hand-edit
numbers there; edit ledger/rules and regenerate.
## Daily Operations — canonical commands
Run from the skill root with `PETASOS_VAULT` exported (the `scripts/*`
wrappers also work by absolute path; `python3 -m petasos.ledger` needs the
skill root as your working directory):
```bash
export PETASOS_VAULT=<abs vault path>
python3 scripts/pipeline.py --dry # SAFE PREVIEW: writes NOTHING, marks nothing seen
python3 scripts/pipeline.py Trust audit
SAFEgrade B · trust 89/100 Nothing in the source contradicts what it says it does. Grade A is reserved for packages that have also passed the behavioural sandbox.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | PASS |
| L1 | Static analysis of the code | PASS |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | PASS |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- none-observed
- Network
- declared (5 observation(s))
- Shell
- none-observed
- Dependencies
- pinned
- Secrets in source
- none-found
Findings (0)
No findings outside the package's declared scope.
Gates applied: no_behavioural_pass.
79e771c005e6full audit observations/trust-audit/skill/nhutdm__petasos-finance-vault.json · Report an issue / request a re-scanAudit history
Every audit this skill has had.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-14 | 79e771c005e6 | SAFE | B | 89 | first audit |
Questions
What does the petasos-finance-vault skill do?
General household-finance skill for Hermes Agent — Obsidian vault, append-only JSONL ledger, pluggable bank-email adapters, verification gates, month close.
Is petasos-finance-vault safe to install?
The audit found nothing in the source that contradicts what it says it does, and graded it B (89/100). Grade A is held back for packages that have also passed a sandboxed behavioural run, which is why a clean skill reads B.
What can petasos-finance-vault access on my machine?
The audit observed that it reaches the network. Each of those is consistent with what it says it does. Secrets in the source: none found.
How current is this page?
The grade is for one exact copy of the source (79e771c005e6), read on 2026-10-14. The repository is watched, and a new audit runs when it changes — this is the first audit.