Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 87 additions & 63 deletions CLAUDE.md

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,16 @@ lint-ci:
uv run ruff format --check
uv run ruff check --no-fix
uv run ty check
uv run python planning/index.py --check

# Print the planning change index (grouped by status) to stdout.
# Print the planning change index (flat, newest-first) to stdout.
index:
uv run python planning/index.py

# Validate planning bundles + decisions; CI runs this.
check-planning:
uv run python planning/index.py --check

test *args:
uv run --no-sync pytest {{ args }}

Expand Down
27 changes: 27 additions & 0 deletions architecture/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Architecture

The living, code-current truth about **what `lite-bootstrap` does now** — one
file per capability, written as prose and dated by git. This is the truth home:
the present-tense companion to `planning/changes/`, which records *how it got
there*.

## Capabilities

- [`config-model.md`](config-model.md) — frozen `BaseConfig` hierarchy, framework
configs via multiple inheritance, `from_dict`/`from_object` semantics, the
`UNSET` sentinel, and the `__post_init__` cascade invariant.
- [`instruments.md`](instruments.md) — `BaseInstrument` lifecycle, the instrument
catalog, the optional-dependency guard, why instruments are non-frozen, the
cross-instrument integrations (Logging↔Sentry, OTel↔Logging, Pyroscope↔OTel),
and OpenTelemetry's single-instance-per-process constraint.
- [`bootstrappers.md`](bootstrappers.md) — the `BaseBootstrapper` hierarchy, skip
ordering at construction, the instrument registry + idempotent teardown, summary
logging, the teardown-on-shutdown attach seam, and the `_lite_bootstrap_*`
app-tagging sentinel convention.

## Promotion rule

When a change alters a capability's behavior, **hand-edit the matching
`architecture/<capability>.md` in the same PR** as the code. That promotion —
reviewed in the same diff, never deferred to a post-merge step — is what keeps
these files true. Code that changes without it silently rots the truth home.
1 change: 1 addition & 0 deletions planning/.convention-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.0.0
42 changes: 25 additions & 17 deletions planning/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ at the repo root; this directory records *how it got there*.

## Conventions

> This section is the portable convention — identical across the
> modern-python repos. The generated change listing (`just index`) and the `## Other` pointers below are repo-local. To adopt elsewhere,
> copy this section plus [`_templates/`](_templates/) and point that repo's
> `CLAUDE.md` Workflow + truth home at it.
> This section is the portable convention, sourced from the canonical repo
> [`lesnik512/planning-convention`](https://github.com/lesnik512/planning-convention)
> (applied version in [`.convention-version`](.convention-version)). To update
> it, run that repo's `APPLY.md` flow. The generated change index (`just index`)
> and the `## Other` pointers below are repo-local.

### Two axes, never mixed

Expand All @@ -32,10 +33,11 @@ A change is a folder `changes/YYYY-MM-DD.NN-<slug>/`:
(`.01`, `.02`, …) that breaks same-date ties so the timeline sorts stably.
- `<slug>` — kebab-case description, not a story ID.

`summary` is written when the change is created (it is the change's
one-liner). The implementing PR then sets `status: shipped` and fills `pr`
and `outcome` **in the branch**, alongside the code and the `architecture/`
promotion — no post-merge bookkeeping, no folder move.
`summary` is written when the change is created (the intent one-liner) and
**finalized at ship** to state the realized result — set in the implementing
PR, alongside the code and the `architecture/` promotion. No post-merge
bookkeeping, no folder move. `date` and `slug` are never written — they are
read from the bundle's directory name.

### Three lanes

Expand Down Expand Up @@ -66,19 +68,25 @@ Templates live in [`_templates/`](_templates/).

### Frontmatter

`design.md` / `change.md`: `status` (draft|approved|shipped|superseded),
`date`, `slug`, `summary` (single line), `supersedes`, `superseded_by`, `pr`,
`outcome`. `plan.md`: `status`, `date`, `slug`, `spec`, `pr`.
`decisions/*.md`: `status` (accepted|superseded), `date`, `slug`, `summary`,
`supersedes`, `superseded_by`, `pr`. Files in
`architecture/` carry **no** frontmatter — living prose, dated by git.
`date` and `slug` are **derived from the directory / file name** — never
repeated in frontmatter. So:

- `design.md` / `change.md`: `summary` (single line) only.
- `plan.md`: **no frontmatter** — its identity is the bundle directory.
- `decisions/*.md`: `status` (accepted|superseded), `summary`, and optional
`supersedes` / `superseded_by`.
- Files in `architecture/` carry **no** frontmatter — living prose, dated by git.

**`summary`** is one line: written at creation as the intent, then **finalized
at ship** to state the realized result — what shipped and its effect. It is the
only field the index renders.

## Index

The listing is **generated**, not maintained — run `just index` to print it:
changes grouped by `status` (In progress / Shipped / Superseded), then
decisions newest-first. The frontmatter in each bundle / decision file is the
single source of truth; there is no committed copy to drift.
changes flat, newest-first, then decisions newest-first. The frontmatter in
each bundle / decision file is the single source of truth; there is no
committed copy to drift.

## Other

Expand Down
9 changes: 1 addition & 8 deletions planning/_templates/change.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
---
status: draft
date: YYYY-MM-DD
slug: my-change
summary: One line — shown in the generated index. Fill at ship time.
supersedes: null
superseded_by: null
pr: null
outcome: null
summary: One line — shown in the generated index. Written at creation; finalize at ship to state the realized result.
---

# Change: One-line capitalized title
Expand Down
3 changes: 0 additions & 3 deletions planning/_templates/decision.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
---
status: accepted # accepted | superseded
date: YYYY-MM-DD
slug: my-decision
summary: One line — shown in `just index`.
supersedes: null
superseded_by: null
pr: null # PR/commit where the decision was made or recorded
---

# One-line capitalized title
Expand Down
9 changes: 1 addition & 8 deletions planning/_templates/design.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
---
status: draft
date: YYYY-MM-DD
slug: my-change
summary: One line — shown in the generated index. Fill at ship time.
supersedes: null
superseded_by: null
pr: null
outcome: null
summary: One line — shown in the generated index. Written at creation; finalize at ship to state the realized result.
---

# Design: One-line capitalized title
Expand Down
12 changes: 1 addition & 11 deletions planning/_templates/plan.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
---
status: draft
date: YYYY-MM-DD
slug: my-change
spec: my-change
pr: null
---

# <slug> — implementation plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use
Expand Down Expand Up @@ -46,9 +38,7 @@ in the spec.

```bash
git add path/to/file.py
git commit -m "<type>: <subject>

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"
git commit -m "<type>: <subject>"
```

---
Expand Down
38 changes: 38 additions & 0 deletions planning/_templates/release.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# <project> <version> — <one-line headline>

<One or two sentences: what this release is and its headline change. Say up
front if there are no behavior/API changes.>

<!-- Keep only the sections that apply; reorder/rename freely. A tiny release
may be just the title + one section. Versioning is tag-driven — the
release tag sets the version (`just publish` runs `uv version`), so there
is no pyproject bump. -->

## Feature

- **<name>.** What it adds and how to use it.

## Fix

- **<name>.** What was broken, now fixed (reference the issue/regression).

## Internal refactors

- **<name>.** What changed under the hood, stated as no behavior change.

## Packaging

- Metadata / build / dependency changes visible to installers.

## Why

Context a reader needs for the headline change. Omit for small releases.

## Downstream

What dependents must do — e.g. bump their version floor — or "No action
needed" when there is no API change. Omit if the project has no downstreams.

## Internals

- Coverage / tooling notes.
7 changes: 0 additions & 7 deletions planning/changes/2026-05-31.01-audit-implementation/design.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
---
status: shipped
date: 2026-05-31
slug: audit-implementation
summary: Criticals (CRIT-1..3) + design issues (DES-1..5) + paired tests across seven sequenced PRs.
supersedes: null
superseded_by: null
pr: null
outcome: "shipped as #89–#95"
---
# Audit Implementation Sequencing

Expand Down
Loading