householdplan
Generate a written household financial plan: policies by domain, an action register, an assumptions table where every value carries a rationale and a revisit trigger, and the scaffolding to keep the plan current after it is written.
A household plan records what you do when something happens, so the decision gets made once, in advance, rather than under pressure. Most plans go stale because nothing forces the assumptions to be revisited and nothing records why a number was chosen. This tool generates both parts: the document, and the review structure around it.
Thirty-one policy rules across eleven domains, two dependencies, no language model, and no network access. The same inputs always produce the same document, because policy text comes from a YAML corpus rather than from generated prose.
Educational. Not legal, tax, or investment advice.
Install
pip install householdplan
Python 3.11+. Two dependencies (pydantic, pyyaml). No network access, no telemetry, no
language model: policy text comes from a YAML corpus, so the same inputs always produce the
same document.
Use
householdplan draft examples/couple.yaml -o plan.md # the plan document
householdplan validate plan.md # structural checks
householdplan scaffold -o planrepo/ # appendices + review template
householdplan export-rules -o rules.json # the corpus, for other runtimes
Use as a library
Everything public is importable from the package root, so internal layout can change without breaking you:
from householdplan import PlanHousehold, PlanSpec, build_document, load_rules, render_markdown
spec = PlanSpec(
household=PlanHousehold(couple=True, taxable=True),
effective_date="2026-03-01",
values={"savings-rate.rate": 20, "reserve-floor.months": 6},
)
document = build_document(spec, load_rules())
markdown = render_markdown(document)
load_rules() caches the parsed corpus, and the rules it returns are frozen, so calling it
per request is cheap and no caller can rewrite policy text for another.
Storing a plan
PlanSpec() is valid with no arguments, which is right for a draft being filled in and
wrong for a payload coming back from storage: a read that fails and returns an empty mapping
would otherwise produce a complete-looking document instead of an error. Load stored specs
through from_stored, which refuses anything untagged:
payload = spec.for_storage() # stamps schema_version
restored = PlanSpec.from_stored(payload)
PlanSpec.from_stored({}) # ValueError: no schema_version
PlanSpec.from_stored(None) # TypeError: not a mapping
This is a backstop rather than a substitute for a storage layer that raises on its own read failures.
What it generates
draft emits a seven-section document:
- Why we manage money this way
- Goals, in priority order
- Policies, grouped by domain
- Action register
- Assumptions
- Review and change policy
- Appendices to write next
scaffold emits the layer that keeps it alive: eleven numbered appendix skeletons (00
Summary through 10 References) with their table headers in place, a quarterly review
template whose sections map one-to-one onto those appendices, and a review log.
Policy domains
Cash flow, liquidity, debt, investing, taxes, equity compensation, insurance, goals, retirement, estate and handoff, governance.
Each rule declares which households it applies to, so a solo household without equity compensation never sees rules written for a couple with vesting stock. A rule you switch off is recorded as a deliberate omission rather than dropped silently, which keeps a later review from relitigating a decision that was already made.
Rules are data
The corpus lives in YAML, one file per domain:
- id: reserve-floor
domain: Liquidity
label: Cash reserve floor and what happens if it breaks
relevant: always
default_on: true
inputs:
- {key: months, label: Reserve floor, kind: num, suffix: months of essential spending}
assumption_keys: [months]
variants:
- when: always
text: "{We} hold at least {n:months} months of essential spending in {t:accounts}.
If reserves fall below that floor, optional taxable investing pauses until
the floor is restored."
relevant and when are boolean expressions over six household flags (couple,
dependents, both_retirement_plans, equity_comp, taxable, near_retirement)
combined with and, or, not, and parentheses. A recursive-descent parser handles them,
so a corpus file cannot execute anything and an unknown flag name fails at load.
Because the corpus is data rather than code, export-rules emits it as JSON for other
runtimes to render, and a single edit to a policy sentence reaches every consumer.
Validation
validate runs ten structural checks: every enabled rule's inputs are bound, every
assumption has a rationale and a revisit trigger, every action has an owner and a due date,
goals are uniquely ranked, the disclaimer is present, no individualized securities advice, no
overstated certainty, every number in the prose traces to a bound input, an effective date is
set, and switched-off domains are recorded rather than dropped.
Scope
This generates a policy document from inputs you supply. It does not run projections, pick investments, or give individualized advice. Numbers you put in come back out with their rationale attached; it does no arithmetic of its own.
Related
The plan document pairs with projection tools rather than replacing them. A projection tells
you whether the numbers work; this records what you will do when they stop working.
planner-lab consumes this package as an optional
extra and can build a plan straight from a typed case file, so the policy figures and the
memo figures come from the same source.
License
MIT
#personal-finance #financial-planning #investment-policy-statement #household-budget
#retirement-planning #financial-independence #document-generation #markdown
#python #pydantic #deterministic #no-llm #open-source-finance #money-management
#financial-literacy
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file householdplan-0.2.1.tar.gz.
File metadata
- Download URL: householdplan-0.2.1.tar.gz
- Upload date:
- Size: 103.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ae89144b7568c956d5ff822dc5c5bbd82495ee6665c5efb3e81fcdfe3401f4a2
|
|
| MD5 |
7febb2da409a01061a577d20067ca25b
|
|
| BLAKE2b-256 |
56086ed16d1150d46cdf671ea7ce9cb9c3ea9fcb8de9a06e799b009322a4830d
|
Provenance
The following attestation bundles were made for householdplan-0.2.1.tar.gz:
Publisher:
release.yml on engineerinvestor/householdplan
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
householdplan-0.2.1.tar.gz -
Subject digest:
ae89144b7568c956d5ff822dc5c5bbd82495ee6665c5efb3e81fcdfe3401f4a2 - Sigstore transparency entry: 2400723890
- Sigstore integration time:
-
Permalink:
engineerinvestor/householdplan@f7af0eb1b6540a29d4858335fb271cfda154d444 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/engineerinvestor
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f7af0eb1b6540a29d4858335fb271cfda154d444 -
Trigger Event:
release
-
Statement type:
File details
Details for the file householdplan-0.2.1-py3-none-any.whl.
File metadata
- Download URL: householdplan-0.2.1-py3-none-any.whl
- Upload date:
- Size: 47.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ddf54c83f7e9a66b88d4ce6f8755d5cb089a84d9d263c9787371746ca6254f1d
|
|
| MD5 |
92447d47cd8bb52765ebe01c384418c1
|
|
| BLAKE2b-256 |
906ca1e439a4ad531295586b1bd7fa1e8b90844ccc56e73bafdc01c08eff380c
|
Provenance
The following attestation bundles were made for householdplan-0.2.1-py3-none-any.whl:
Publisher:
release.yml on engineerinvestor/householdplan
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
householdplan-0.2.1-py3-none-any.whl -
Subject digest:
ddf54c83f7e9a66b88d4ce6f8755d5cb089a84d9d263c9787371746ca6254f1d - Sigstore transparency entry: 2400724275
- Sigstore integration time:
-
Permalink:
engineerinvestor/householdplan@f7af0eb1b6540a29d4858335fb271cfda154d444 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/engineerinvestor
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f7af0eb1b6540a29d4858335fb271cfda154d444 -
Trigger Event:
release
-
Statement type: