Skip to main content

householdplan

ci pypi python license checked with mypy ruff

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:

  1. Why we manage money this way
  2. Goals, in priority order
  3. Policies, grouped by domain
  4. Action register
  5. Assumptions
  6. Review and change policy
  7. 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

householdplan-0.2.1.tar.gz (103.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

householdplan-0.2.1-py3-none-any.whl (47.6 kB view details)

Uploaded Python 3

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

Hashes for householdplan-0.2.1.tar.gz
Algorithm Hash digest
SHA256 ae89144b7568c956d5ff822dc5c5bbd82495ee6665c5efb3e81fcdfe3401f4a2
MD5 7febb2da409a01061a577d20067ca25b
BLAKE2b-256 56086ed16d1150d46cdf671ea7ce9cb9c3ea9fcb8de9a06e799b009322a4830d

See more details on using hashes here.

Provenance

The following attestation bundles were made for householdplan-0.2.1.tar.gz:

Publisher: release.yml on engineerinvestor/householdplan

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for householdplan-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 ddf54c83f7e9a66b88d4ce6f8755d5cb089a84d9d263c9787371746ca6254f1d
MD5 92447d47cd8bb52765ebe01c384418c1
BLAKE2b-256 906ca1e439a4ad531295586b1bd7fa1e8b90844ccc56e73bafdc01c08eff380c

See more details on using hashes here.

Provenance

The following attestation bundles were made for householdplan-0.2.1-py3-none-any.whl:

Publisher: release.yml on engineerinvestor/householdplan

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page